我在处理以下代码时遇到了问题:
#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和GNUGCC编译器在我的计算机上运行它时,它没有任何问题。但是当我在另一台机器上使用它时(也用Code:Blocks和LLVM Clang编译器),我得到错误
隐式转换改变符号性:'int'到'unsigned long' [-Werror,-Wsign-conversion]
此错误引用行
char* string =(char*)malloc((number+1)*sizeof(char));
如果我得到的错误消息是正确的,有一些“int”被隐式转换为“unsigned long”,但我没有看到这种情况发生在哪里。
你能给我解释一下吗?
2条答案
按热度按时间e4eetjau1#
这是一个警告,编译器认为是由于编译器选项
-Werror
和-Wsign-conversion
引起的错误。在表达式中
在
malloc
的调用中使用的操作数sizeof( char )
具有无符号整数类型size_t
,其是类型unsigned long
的别名。另一方面,操作数number+1
具有带符号类型int
。类型size_t
的秩高于类型int
的秩。这意味着由于通常的算术转换,int
类型的操作数将隐式转换为size_t
类型,因此可能会丢失其符号。要解决这个问题,只需像这样声明函数参数
传递一个有符号的值给分配内存的函数是没有意义的,而且函数
malloc
的参数的类型是size_t
。为了使它清楚,然后考虑下面的简单程序。
它的输出可能看起来像
正如你所看到的,类型为
int
的负变量number
被转换为无符号整数类型size_t
,变成了一个非常大的无符号整数。w6lpcovy2#
malloc
函数的签名是size_t
是一个unsigned整数类型,而int
是有符号的。您正在将值(number+1)*sizeof(char)
传递给此函数。clang基本上会问你:如果传入的
number
的值为负,函数会发生什么?要摆脱这种情况,要么显式地将
number
转换为size_t
,以告诉编译器您知道它不会为负,要么首先将number
的类型更改为size_t
。另外请注意,这只是一个错误,因为clang是用
-Werror
标志调用的(将所有警告视为错误)。否则,这将只是一个 * 警告 *,这意味着程序仍然可以编译,但编译器会通知您潜在的问题。这并不是说-Werror
是一个坏主意,事实上,除非您正在进行快速原型开发,否则建议您使用-Werror
。注意:在这个特定的例子中,转换实际上已经在 * 乘法 * 的过程中发生了。我的clang给出了以下输出:
如果你仔细看,它会给
number+1
(类型为int
的操作数)和*
(操作符)加下划线。sizeof(char)
的类型是size_t
(这里显示为等价的unsigned long
)。所以要执行乘法,clang已经转换了类型。