我遇到了以下代码的问题:
#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
的符号类型为int
。size_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_t
是unsigned整数类型,而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必须转换类型。