考虑以下代码:
#include <memory.h>
#include <stdlib.h>
void Foo()
{
const char ** caps = malloc( sizeof( char * ) );
memset( caps, 0, sizeof( char * ) );
}
使用gcc 4.9.2 -pedantic可以正常编译,但是clm 18(来自VS2013的那个)和默认选项warning C4090: 'function' : different 'const' qualifiers
在memset行上说。
现在caps
是一个指向const char的指针吗?因此,指针本身不是const,因此void*
我认为它应该可以毫无问题地转换为,但是cl似乎会自动const void*
从中产生警告。这是对正在发生的事情的正确解释吗?这是非标准行为,对吗?
编译器过于狂热(读为:编译器错误)。
const char** caps
表示caps
是一个指向常数的a的指针(非恒定)char
。也就是说,您保证不会char
通过over的间接修改caps
。
这意味着您与编译器正式签订了以下合同:
caps
。*caps
(在char*
这caps
点)。**caps
(在char
这*caps
点,(这caps
点))通过这条产业链的指针。关于改变该字符的值的其他任何人(例如,别名指针)都一无所知。
const char ** caps = malloc(sizeof(char *));
caps
用合法的值初始化。万一malloc
失败,该值是一个空指针,但是从语言的角度来看,这通常也是完全合法的(尽管这会导致后面memset
的代码崩溃)。在C ++中,将需要显式地转换void*
by的返回值malloc
,但是C允许这种事情很好。
memset(caps, 0, sizeof(char*));
使我的头发站起来(我是C ++程序员),但是从C语言的角度来看,这绝对是一件合法的事情。
它的作用是覆盖到目前为止已分配但尚未初始化(并由指向caps
)的内存块,该内存块包含第二个指针,该第二个指针的零字节数等于指针(char
指针的大小)。
带非常量的库函数memset
仅用您提供的值(此处为零)void*
填充您要求的字节数(此处sizeof(char*)
为)。它与您与编译器签订的合同无关,也不需要在意。但是即使如此,它也没有违反任何规则。它会覆盖指针,而不是指向常量的值。
是的,它在不是s数组的char
东西中写入了几个值(这就是为什么我的头发挺立的原因),但是……那是合法的。就是这样char
memset
毕竟,它应该可以做到,并且很可能“按预期工作”。它将指针设置为零位模式,除了一些非常罕见的奇特体系结构外,该模式对应于空指针。
绝对不会**caps
更改(或什至访问)内存位置,因此所有这些都是完全合法的,您没有违反任何承诺。
因此,警告是错误的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句