char和int是否可以在C中用于函数参数?

时间:2014-03-13 18:15:58

标签: c++ c char int alphanumeric

我使用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;
}

输出:

str= abcdABCD1234, result=1

The entered serial number seems incorrect.It's less than 10 characters.
str= abcdef##, result=0

str= abcdABCD1234$#, result=0

2 个答案:

答案 0 :(得分:10)

您无需更改它。在将char传递给int之前,编译器会隐式将isalnum转换为isalnumint之类的函数会使用fgetc个参数,因为像int这样的函数会返回EOF个值,这样就可以存在char之类的特殊值。

更新:正如其他人所提到的,请注意glibc的负值。您的C库版本可能可以小心实施,以便处理负值而不会导致任何运行时错误。例如,int(标准C库的GNU实现)似乎通过向isalnum参数添加128来处理负数。 * 但是,您并不总是能够依靠<ctype.h>(或任何其他-57函数)悄悄地处理负数,所以养成不检查的习惯是一个非常糟糕的主意。

* 从技术上讲,它不会在参数本身中添加128,而是它似乎使用参数作为数组的索引,从索引128开始,这样传入,比方说, 71将导致访问数组的索引array[-57+128]。但结果是相同的,因为(array+128)[-57]和{{1}}指向同一位置。

答案 1 :(得分:2)

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

但是isalnum和其他C函数存在特定问题,无法进行字符分类和转换。来自ISO / IEC 9899:TC2 7.4 / 1(强调我的):

  

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

因此,如果char是签名类型(这取决于实现),如果您遇到带有负值的char,那么它将转换为int传递给函数之前的负值。负数不能表示为unsigned char。代表unsigned char的数字为0UCHAR_MAX。因此,如果传入任何EOF以外的任何负值,则会有未定义的行为。

出于这个原因,你应该在C:

中编写这样的代码
if( !isalnum((unsigned char)*charPtr) )

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

if( !isalnum(static_cast<unsigned char>(*charPtr)) )

这一点值得学习,因为在第一次遇到它时似乎很荒谬:不会将char传递给角色函数

或者,在C ++中,标题isalnum中存在<locale>的双参数版本。此函数(及其朋友)确实将char作为输入,因此您不必担心负值。你会惊讶地发现第二个参数是一个语言环境; - )