C++ C中函数参数的char和int可以互换吗?

C++ C中函数参数的char和int可以互换吗?,c++,c,char,int,alphanumeric,C++,C,Char,Int,Alphanumeric,我编写了一些代码,用isalnum验证序列号在C中是否为字母数字。我编写的代码假设isalnum输入是char。一切顺利。但是,在稍后查看isalnum之后,我发现它希望输入为int。我的代码是否可以更改它 如果我真的需要改变,正确的方法是什么?我应该声明一个int并将其设置为char并将其传递给isalnum吗?这被认为是糟糕的编程实践吗 提前谢谢 #include <stdlib.h> #include <string.h> #include <stdbool.

我编写了一些代码,用isalnum验证序列号在C中是否为字母数字。我编写的代码假设isalnum输入是char。一切顺利。但是,在稍后查看isalnum之后,我发现它希望输入为int。我的代码是否可以更改它

如果我真的需要改变,正确的方法是什么?我应该声明一个int并将其设置为char并将其传递给isalnum吗?这被认为是糟糕的编程实践吗

提前谢谢

#include <stdlib.h>
#include <string.h>
#include <stdbool.h>


bool VerifySerialNumber( char *serialNumber ) { 
int num;
char* charPtr = serialNumber;


if( strlen( serialNumber ) < 10 ) { 
    printf("The entered serial number seems incorrect.");
    printf("It's less than 10 characters.\n");
    return false;
}   

while( *charPtr != '\0' ) { 
    if( !isalnum(*charPtr) ) { 
    return false;
    }   
    *charPtr++;
}   
return true;
}


int main() {
char* str1 = "abcdABCD1234";
char* str2 = "abcdef##";
char* str3 = "abcdABCD1234$#";
bool result;

result = VerifySerialNumber( str1 );
printf("str= %s, result=%d\n\n", str1, result);

result = VerifySerialNumber( str2 );
printf("str= %s, result=%d\n\n", str2, result);

result = VerifySerialNumber( str3 );
printf("str= %s, result=%d\n\n", str3, result);
return 0;
}

你不需要改变它。编译器将在将字符传递给isalnum之前隐式地将其转换为int。像isalnum这样的函数采用int参数,因为像fgetc这样的函数返回int值,这允许像EOF这样的特殊值存在

更新:正如其他人提到的,小心使用char的负值。您的C库版本可能会小心地实现,以便在不导致任何运行时错误的情况下处理负值。例如,标准C库的GNU实现glibc似乎通过在int参数中添加128来处理负数。*但是,您不能总是指望isalnum或任何其他函数安静地处理负数,因此养成不检查的习惯将是一个非常糟糕的主意


*从技术上讲,它并没有将128添加到参数本身,而是似乎将参数用作数组的索引,从索引128开始,这样传入,例如,-57将导致访问数组的索引71。结果是一样的,因为数组[-57+128]和数组+128[-57]指向同一个位置。

您不需要更改它。编译器将在将字符传递给isalnum之前隐式地将其转换为int。像isalnum这样的函数采用int参数,因为像fgetc这样的函数返回int值,这允许像EOF这样的特殊值存在

更新:正如其他人提到的,小心使用char的负值。您的C库版本可能会小心地实现,以便在不导致任何运行时错误的情况下处理负值。例如,标准C库的GNU实现glibc似乎通过在int参数中添加128来处理负数。*但是,您不能总是指望isalnum或任何其他函数安静地处理负数,因此养成不检查的习惯将是一个非常糟糕的主意

*从技术上讲,它并没有将128添加到参数本身,而是似乎将参数用作数组的索引,从索引128开始,这样传入,例如,-57将导致访问数组的索引71。但结果是一样的,因为数组[-57+128]和数组+128[-57]指向同一位置。

通常可以将char值传递给接受int的函数。它将转换为具有相同值的int。这不是一个坏习惯

但是,isalnum和其他用于字符分类和转换的C函数有一个特定的问题。这是来自ISO/IEC 9899:TC2 7.4/1的:

在所有情况下,参数都是int,其值应为 可表示为无符号字符,或应等于 宏EOF。如果参数有任何其他值,则行为为 未定义

因此,如果char是有符号类型,这取决于实现,如果遇到一个具有负值的char,那么在将其传递给函数之前,它将被转换为具有负值的int。负数不能表示为无符号字符。表示为unsigned char的数字是0到UCHAR_MAX。因此,如果传入除EOF之外的任何负值,则具有未定义的行为

因此,您应该在C中编写如下代码:

if( !isalnum((unsigned char)*charPtr) )

或C++中,你可能更喜欢:

if( !isalnum(static_cast<unsigned char>(*charPtr)) )
这一点值得学习,因为在第一次遇到它时,它看起来很荒谬:不要将char传递给character函数

或者,在C++中,在标题中有一个ISALNUM的两个参数版本。这个函数和它的朋友们确实把一个字符作为输入,所以你不必担心负值。你会惊讶地发现第二个参数是一个区域设置-

通常可以将char值传递给接受int的函数。它将被转换为具有相同值的int。这不是一个坏习惯

但是,isalnum和其他用于字符分类和转换的C函数有一个特定的问题。这是来自ISO/IEC 9899:TC2 7.4/1的:

在所有情况下,参数都是int,其值应为 可表示为无符号字符,或应等于 宏EOF。如果参数有任何其他值,则行为为 未定义

所以,如果char是有符号类型,这就是de实现 pendent,并且如果遇到一个具有负值的char,那么在将其传递给函数之前,它将被转换为一个具有负值的int。负数不能表示为无符号字符。表示为unsigned char的数字是0到UCHAR_MAX。因此,如果传入除EOF之外的任何负值,则具有未定义的行为

因此,您应该在C中编写如下代码:

if( !isalnum((unsigned char)*charPtr) )

或C++中,你可能更喜欢:

if( !isalnum(static_cast<unsigned char>(*charPtr)) )
这一点值得学习,因为在第一次遇到它时,它看起来很荒谬:不要将char传递给character函数


或者,在C++中,在标题中有一个ISALNUM的两个参数版本。这个函数和它的朋友们确实把一个字符作为输入,所以你不必担心负值。你会惊讶地发现第二个参数是一个区域设置-

谢谢,@MikeHolt这被认为是糟糕的编程实践还是可以的?对有符号值和无符号值一定要小心。如果只使用0-127范围内的字符,则没有问题。@user1527227不,这是一种不错的编程实践。错误的编程实践是在不采取预防措施确保值不会被截断的情况下,将int传递给需要char的函数。谢谢,@MikeHolt这被认为是错误的编程实践还是可以的?请小心有符号值与无符号值。如果只使用0-127范围内的字符,则没有问题。@user1527227不,这是一种不错的编程实践。糟糕的编程实践是将int传递给需要char的函数,而不采取预防措施确保值不会被截断。