sti*_*ijn 9 c gcc pointers visual-c++
考虑以下代码:
#include <memory.h>
#include <stdlib.h>
void Foo()
{
const char ** caps = malloc( sizeof( char * ) );
memset( caps, 0, sizeof( char * ) );
}
Run Code Online (Sandbox Code Playgroud)
使用gcc 4.9.2 -pedantic编译精细但是cl 18(来自VS2013的那个)warning C4090: 'function' : different 'const' qualifiers在memset行上显示默认选项.
现在caps是一个指向const char指针的指针?所以指针本身不是const因此它应该转换为void*没有问题,我认为,但cl似乎自动const void*从它生成警告.这是对正在发生的事情的正确解释吗?这是非标准行为,对吧?
编译器过于热心(读作:编译器错误)。
const char** caps意味着 thatcaps是一个指针(不是常量),指向另一个指向常量的指针(也不是常量)char。也就是说,您保证不会char通过经过的间接修改来修改它caps。
这意味着您正式与编译器签订以下合同:
caps。*caps(指向的内容char*)caps。**caps(char指向*caps(caps指向))。没有提及任何其他人(例如别名指针)更改该字符的值。
const char **caps = malloc( sizeof( char * ) );
caps用一个值初始化,这是合法的。如果malloc失败,这个值是一个空指针,但是从语言的角度来看,这通常也是完全合法的(尽管它会导致以下memset崩溃)。在 C++ 中,您需要显式转换void*由 返回的值malloc,但 C 允许这种事情就好。
memset(caps, 0, sizeof(char*));
Run Code Online (Sandbox Code Playgroud)
这让我毛骨悚然(我是一名 C++ 程序员),但从 C 语言的角度来看,这仍然是完全合法的事情。
它的作用是覆盖迄今为止已分配但未初始化(并由 指向caps)的内存块,该内存块包含第二个指针,其零字节数等于指针(char碰巧是指针)的大小。
库函数memset采用非常量,只需用您提供的值(此处:零)void*填充您要求的字节数(此处)。sizeof(char*)它不会也不需要关心您与编译器签订的合同。但即便如此,它也没有违反任何规则。它覆盖指针,而不是指向的常量值。
是的,它把几个值写入到不是s数组的char东西中(这就是我头发竖起来的原因),但是……那是……合法的。毕竟,这正是应该做的,而且很可能“按预期工作”。它将指针设置为零位模式,除了一些非常罕见的奇异架构之外,它对应于空指针。charmemset
内存位置在任何时候都**caps没有改变(甚至没有被访问),所以所有这一切都是完全合法的,你没有违背任何承诺。
因此,该警告是错误的。
| 归档时间: |
|
| 查看次数: |
1687 次 |
| 最近记录: |