int main()
{
int *d=0;
printf("%d\n",*d);
return 0;
}
这很好。
>cc legal.c
> ./a.out
0
如果我将语句int *d=0;
更改为int *d=1;
我看到了错误。
cc: "legal.c", line 6: error 1522: Cannot initialize a pointer with an integer constant other than zero.
所以很明显它只允许为零。我想知道当我们执行此操作时int *d=0
内部会发生什么,这使得它成为有效的语法。
我只是出于好奇而问这个!
答案 0 :(得分:5)
我很惊讶您运行代码时没有得到SEGFAULT。 printf语句中的*d
取消引用指针。但是,要回答您的问题,C ++允许将0作为任何对象的默认初始值设定项,这就是为什么它可以用于将指针初始化为null(0和null相同)的原因。值为1时,您要求编译器将整数转换为指针,这需要显式转换。
答案 1 :(得分:3)
使用0
初始化指针时,0
会隐式转换为空指针。空指针的外观取决于您的平台,编译器将使用正确的二进制值。
当您尝试使用1
(或任何其他非零整数)初始化指针时,编译器不知道将此值转换为有效指针并发出警告。
答案 2 :(得分:2)
您正在堆栈上创建一个名为d
的指针变量,该变量被称为“指向一个整数”。然后将该指针变量赋值为0,使其指向有效的内存地址0x0(与C中的NULL
相同。)
为了更清楚,int *d = 0
与:
int *d;
d = 0; // set it to address 0
如果你想指向一个整数1
,那么你需要这个:
int x = 1;
int *d = &x; // "set it to 'address of x'"
答案 3 :(得分:0)
如果* d = 0,则整数指针d被初始化为0,这是有效的。基本上你是在声明一个整数指针,所以初始化指针是有意义的。
但是,你不想初始化指针,而是初始化它指向的内存,这是不正确的。
执行* d = 1时,指针值变为1,当执行printf语句时,它将尝试访问地址1处的值,这是不允许的。
希望这有帮助。
答案 4 :(得分:0)
在“工作”示例中,您将取消引用空指针,并且语言将它找到的任何位作为参数放入printf。它的工作原理完全取决于编译器和机器的完全依赖于实现的功能,并且可能会在另一个实现中出现段错误。
代码工作似乎表明你的编译器在幕后做了一些奇怪的事情,试图“保护”编码器免于一个非常常见的错误;这是一个坏主意。我很想看看编译器使用cc -s
答案 5 :(得分:0)
在ISO-C99中,有两种类型的空指针常量:值为0
的整数常量表达式 - 例如0
,1 - 1
,(int)0.0
- 以及此类表达式转为void *
- 例如(void *)0
,通常用于定义NULL
。
将空指针常量转换为任意指针类型会产生该类型的空指针。此转换是隐式的,但实际上可能涉及地址转换,因为标准不需要空指针来使位代表0。
此转换也是为函数指针类型定义的,即使将对象指针转换为函数指针通常也是非法的:
void (*foo)(void) = (void *)0; // valid
void *bar = 0; // valid
void (*baz)(void) = (void (*)(void))bar; // invalid even with explicit cast
这也意味着您可以使用0
初始化任何标量类型而不进行强制转换,并且它是唯一的值,这是真的:将0
转换为指针类型将始终产生空指针,转换任何其他整数值是可能的,但需要显式转换,具有实现定义的结果,并且可能由于对齐或地址空间限制而失败。