缩小从 'long' 到有符号类型 'char' 的转换是实现定义的(C 中的 strtol 函数)
Narrowing conversion from 'long' to signed type 'char' is implementation-defined (strtol function in C)
我正在尝试使用 strtol 将输入的字符转换为整数。这是源代码的一部分:
char option;
char *endptr;
printf("=========================================Login or Create Account=========================================\n\n");
while(1) {
printf("Welcome to the Bank management program! Would you like to 1. Create Account or 2. Login?\n>>> ");
fgets(&option, 1, stdin);
cleanStdinBuffer();
option = strtol(&option, &endptr, 10);
在 strtol 函数中,我收到一条警告:
Clang-Tidy: Narrowing conversion from 'long' to signed type 'char' is implementation-defined
谁能告诉我哪里做错了?
char
只能包含 long
值的很小一部分。 strtol returns long
并将其分配给 char
.
这次调用fgets
fgets(&option, 1, stdin);
总是将字符 option
设置为终止零字符 '[=16=]'
,前提是用户没有中断输入。
这是一个演示程序。
#include <stdio.h>
int main(void)
{
char c = 'A';
printf( "Before calling fgets c = %d\n", c );
fgets( &c, 1, stdin );
printf( "After calling fgets c = %d\n", c );
return 0;
}
程序输出为
Before calling fgets c = 65
After calling fgets c = 0
与用户输入的内容无关。这里的值65
是调用fgets
.
之前保存在变量c中的字符'A'
的ASCII码
如果你想输入一个字符,那么你应该使用
scanf( " %c", &input );
注意转换说明符前的空格。
在这个调用之后你可以检查用户是否输入了像
这样的数字
#include <ctypes.h>
//...
if ( isdigit( ( unsigned char )input ) ) input = input - '0';
并将变量输入设为[0, 9]
.
范围内对应的整数值
Clang-Tidy 警告您在此处进行的隐式转换,您将 strtol
的 long
return 值分配给 char
:
option = strtol(&option, &endptr, 10);
如果这是故意的,并且您确定该值将在 [-128,127] 范围内,这不一定是一个问题(这只是一个警告),但即便如此我还是建议显式地转换 return 类型的 strtol
,使用 int8_t
而不是 char
并且不重用 option
变量作为 return 值。换句话说:
int8_t value = (int8_t)strtol(&option, &endptr, 10);
如果不是故意的,我建议您简单地使用 long
作为您分配给 strtol 的 return 值的变量的类型,因此:
long value = strtol(&option, &endptr, 10);
Clang-tidy 没有警告您的是 strtol
的第一个参数应该是指向包含以 0 结尾的字符串的字符缓冲区的指针,而不是指向单个字符的指针。这也是 fgets 的问题。有两种方法可以解决这个问题:
使选项成为至少包含两个字符的 char
数组,
改用 fgetc 并将您的代码修改为如下内容:
int option = fgetc(stdin);
if (option == '1') {
/*Create Account */
} else if (option == '2') {
/* Login */
}
else {
/* Error */
}
我觉得后者看起来干净多了
我正在尝试使用 strtol 将输入的字符转换为整数。这是源代码的一部分:
char option;
char *endptr;
printf("=========================================Login or Create Account=========================================\n\n");
while(1) {
printf("Welcome to the Bank management program! Would you like to 1. Create Account or 2. Login?\n>>> ");
fgets(&option, 1, stdin);
cleanStdinBuffer();
option = strtol(&option, &endptr, 10);
在 strtol 函数中,我收到一条警告:
Clang-Tidy: Narrowing conversion from 'long' to signed type 'char' is implementation-defined
谁能告诉我哪里做错了?
char
只能包含 long
值的很小一部分。 strtol returns long
并将其分配给 char
.
这次调用fgets
fgets(&option, 1, stdin);
总是将字符 option
设置为终止零字符 '[=16=]'
,前提是用户没有中断输入。
这是一个演示程序。
#include <stdio.h>
int main(void)
{
char c = 'A';
printf( "Before calling fgets c = %d\n", c );
fgets( &c, 1, stdin );
printf( "After calling fgets c = %d\n", c );
return 0;
}
程序输出为
Before calling fgets c = 65
After calling fgets c = 0
与用户输入的内容无关。这里的值65
是调用fgets
.
'A'
的ASCII码
如果你想输入一个字符,那么你应该使用
scanf( " %c", &input );
注意转换说明符前的空格。
在这个调用之后你可以检查用户是否输入了像
这样的数字#include <ctypes.h>
//...
if ( isdigit( ( unsigned char )input ) ) input = input - '0';
并将变量输入设为[0, 9]
.
Clang-Tidy 警告您在此处进行的隐式转换,您将 strtol
的 long
return 值分配给 char
:
option = strtol(&option, &endptr, 10);
如果这是故意的,并且您确定该值将在 [-128,127] 范围内,这不一定是一个问题(这只是一个警告),但即便如此我还是建议显式地转换 return 类型的 strtol
,使用 int8_t
而不是 char
并且不重用 option
变量作为 return 值。换句话说:
int8_t value = (int8_t)strtol(&option, &endptr, 10);
如果不是故意的,我建议您简单地使用 long
作为您分配给 strtol 的 return 值的变量的类型,因此:
long value = strtol(&option, &endptr, 10);
Clang-tidy 没有警告您的是 strtol
的第一个参数应该是指向包含以 0 结尾的字符串的字符缓冲区的指针,而不是指向单个字符的指针。这也是 fgets 的问题。有两种方法可以解决这个问题:
使选项成为至少包含两个字符的
char
数组,改用 fgetc 并将您的代码修改为如下内容:
int option = fgetc(stdin); if (option == '1') { /*Create Account */ } else if (option == '2') { /* Login */ } else { /* Error */ }
我觉得后者看起来干净多了