c -改变符号的隐式转换在哪里?



我遇到了以下代码的问题:

#include <stdio.h>
#include <stdlib.h>
void someFunction(int number);
int main()
{
printf("Hello world!n");
return 0;
}
void someFunction(int number)
{
char* string = (char*) malloc((number+1)*sizeof(char));
}

当我用Code::Blocks IDE和GNU GCC编译器在我的计算机上运行它时,它没有任何问题。但是当我在另一台机器上使用它时(也使用Code:Blocks和LLVM Clang Compiler编译器),我得到错误

隐式转换将signed: 'int'变为'unsigned long'[-Werror, -Wsign-conversion]

这个错误指的是

这一行

char *字符串= (char *) malloc((数+ 1)* sizeof (char));

如果我得到正确的错误信息,有一些"int"它被隐式地转换为"unsigned long",但我没有看到这是在哪里发生的。

你能给我解释一下吗?

由于编译器选项-Werror-Wsign-conversion,这是一个被编译器认为是错误的警告。

在表达式

(number+1)*sizeof(char)

malloc的调用中使用,操作数sizeof( char )具有无符号整数类型size_t,是unsigned long类型的别名。另一方面,操作数number+1的符号类型为intsize_t类型的排名比int类型的排名高。这意味着由于通常的算术转换,int类型的操作数将隐式地转换为size_t类型,因此可以丢失其符号。

要解决这个问题,只需像 那样声明函数参数
void someFunction(size_t number);

向分配内存的函数传递带符号的值是没有意义的。函数malloc的参数类型为size_t

为了使它更清楚,请考虑下面这个简单的程序。

#include <stdio.h>
int main( void )
{
int number = -1;
printf( "( size_t )number = %zun", ( size_t )number );
}

它的输出可能看起来像

( size_t )number = 4294967295

可以看到,int类型的负变量number转换为无符号整数类型后,size_t变成了一个非常大的无符号整数。

malloc函数的签名为

void* malloc(size_t size);

size_tunsigned整数类型,而int是有符号的。您正在将值(number+1)*sizeof(char)传递给该函数。

clang基本上是在问你:如果传递给它的number的值是负的,这个函数会发生什么?

要摆脱这种情况,要么显式地将number转换为size_t,告诉编译器你知道它不会是负的,或者首先将number的类型更改为size_t

还请注意,这只是一个错误,因为clang是带-Werror标志调用的(将所有警告视为错误)。否则,这将只是一个警告,这意味着程序仍然可以编译,但编译器会通知您潜在的问题。这并不是说-Werror是一个坏主意,事实上,除非你正在做快速原型,否则它是推荐实践。

注意在这个特定的例子中,转换实际上已经在乘法期间发生了。clang给出如下输出:

main.c:14:40: error: implicit conversion changes signedness: 'int' to 'unsigned long' [-Werror,-Wsign-conversion]
char* string = (char*) malloc((number+1)*sizeof(char));
~~~~~~^~ ~

如果你仔细看,它下划线number+1(类型为int的操作数)和*(操作符)。sizeof(char)的类型是size_t(此处显示为等效的unsigned long)。因此,要执行乘法运算,clang必须转换类型。

相关内容

  • 没有找到相关文章

最新更新