C memset 警告

3

这是我的警告。

warning: passing argument 2 of ‘memset’ makes integer from pointer without a cast

然后我进行了如下更改(将NULL改为0)。
Before Change : memset(key, NULL, KEY_BYTES);
After Change : memset(key, 0, KEY_BYTES);

警告已被解除。

我正在使用Linux和GCC编译器,C语言。

这是正确的操作吗?


4
当您想表示“零”的意思时,请勿使用“NULL” 。 - Roger Pate
6个回答

13

根据实现方式,C标准库有时将NULL定义为零整数(这将避免您看到的警告),但有时将NULL定义为零强制转换为void指针。后一种实现会引起您看到的警告。

回答您具体的问题,您在这种情况下不应该使用NULL。无论实现如何,NULL都旨在用作空指针,而不是整数零的同义词。如果您想使用memset将一块内存填充为零,则应将零作为第二个参数传递,而不是NULL。

引用自http://en.wikipedia.org/wiki/Stdlib.h

NULL

stdlib.h和stddef.h头文件定义了宏NULL,它产生一个null指针常量,并表示一个指针值,保证不指向内存中的有效地址。

变体

NULL可以被定义为等于int零、long int零或零强制转换为void *指针的常量表达式:

#define NULL 0
#define NULL 0L
#define NULL ((void*)0)

尽管在C中,空指针常量始终由符号常量0或0强制转换为void指针表示,但这样的指针的实际位表示因系统而异,可能包含一位。


3
memset的第二个参数的类型是int。在C语言中,NULL是“空指针常量”。根据标准规定:
“具有值为0的整数常量表达式,或这种表达式转换为类型void *,被称为‘空指针常量’。”
因此,在这种情况下,NULL可以定义为(void *)0或等同形式。如果您将指针转换为整数,则memset调用是错误的。
另一种方法是可行的:如果您在预期空指针的地方使用0,编译器会为您执行转换。因此,给定类型T,以下代码将同时将pq设置为null指针:
T *p = NULL;
T *q = 0;

此外,针对指针 p,下列语句等价:

if (p) ...
if (p != NULL) ...
if (p != 0) ...

这是因为0很特殊:在指针上下文中,它会自动转换为null指针常量。而指针则永远不会隐式地转换为整数。任何整数除了0以外,也永远不会隐式地转换为指针。
最后,在下面的代码中,即使i的值为0,在分配给p时它也不是一个空指针常量:
int i = 0;
int *p = i;

在符合模式下编译时,上述内容会触发警告。

(上述内容有点离题,但我希望它不完全离题。)


3
可能NULL被定义为((void*)0)。两个版本都可以正确工作,但第二个看起来更好 - memset需要一个数字而不是指针。

1

是的,它们有相同的效果。编译器必须将NULL视为特殊的NULL指针(而一些更原始的编译器仅仅使用 #define NULL 0),并且memset的第二个参数是类型为int的,因此通过将其更改为0,您正在使用空值但满足int要求。


#define NULL 0 不是“更原始的”。这是C++标准的做法,(void)0甚至在C++中都不允许。在C语言中,(void)0更常用/更符合标准。 - sbi
1
@sbi 你漏了一个星号:(void*)0 - user47322
@Charlie:当然。对于那个愚蠢的错误我很抱歉。不过除此之外,我认为我的想法是正确的。 - sbi

0

memset函数的第二个参数应该是一个字符而不是任何指针。在你的第一次调用中,你传递了一个空指针NULL,它在C语言中指向空地址。这就是为什么会出现错误。在第二次调用中,你将0字节分配给了所给定的内存。


0

在使用memset(key, NULL, KEY_BYTES);时,NULL是(int零的void*类型转换)即(void*)0。 而且,memset的第二个参数应该是"unsigned int"类型,这就是为什么会显示警告。

根据您使用的编译器不同,它的行为也会有所不同。 使用gcc编译器会发出警告(关于数据类型转换),并将接受给定参数值中最接近的可用值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接