我对某些代码变体有些麻烦。
int *p = 5;
printf("%d\n", *p);
输出:SEGMENTATION FAULT
int *p = 5;
printf("%d\n", p);
输出:5
这里发生了什么?
答案 0 :(得分:2)
注意:这个答案只是为了帮助OP更好地理解指针(我希望),而不是实际回答问题本身。
让我们创建一个小的工作程序,显示指针和值之间的区别:
#include <stdio.h>
int main(void)
{
int i = 5; // Define a variable, initialize it with a value
int *p = &i; // Define a pointer, make it point to the location of the variable i
printf("The value of i is %d\n", i); // Should be pretty obvious
// Dereference the pointer, fetching the value stored in the variable i
// Will say the value of *p is 5, because *p is actually the variable i
printf("The value of *p is %d\n", *p);
// Print the address of i, the location of the variable in memory
printf("The location of the variable i is %p\n", (void *) &i);
// Print the address of i again, using the pointers value
printf("The value of p is %p\n", (void *) p); // Note: No dereferencing
// Print the address of the variable p, i.e. where p is stored in memory
printf("The location of the variable p is %p\n", (void *) &p); // Note use of address-of operator &
return 0;
}
变量的实际地址(位置),实际打印的最后三个printf
调用的内容将有所不同。变量的位置取决于编译器和操作系统。
稍微“图形化”可以看到类似这样的事情:
+----------------------------------+ | the variable i, contents equal 5 | <--\ +----------------------------------+ | | the variable p, contents depends | ---/ +----------------------------------+
从上面的“图片”中,变量p
指向到变量i
。
现在对于重要部分:指针必须指向有效位置,如果要取消引用它,即如果要获取其指向的位置的内容。如果没有,那么您将有未定义的行为。
然而,只要你没有尝试取消引用它,只是用任何随机值初始化指针本身不是问题。
答案 1 :(得分:1)
在这两种情况下,行为都是未定义的:
int *p = 5;
定义指向int
的指针,初始化了5
的硬编码值,很可能无效。 printf("%d\n", *p);
取消引用此指针,该指针具有无效值,因此会出现分段错误。
在第二个示例中,printf("%d\n", p);
打印指针的值,因此得到5
,但转换说明符%d
对指针的值无效,因此行为未定义,其他系统的输出可能不同。
int *p = 5; printf("%d\n", (int)p);
解决了这个问题,但从int
到int *
的隐式转换仍无法保证成功。此类代码仅用于非常特定的环境,例如嵌入式系统或操作系统。提高编译器警告级别可让编译器为此发出警告甚至错误(gcc -Wall
或clang -Weverything
...)
C11标准说:
6.3.2.3指针
整数可以转换为任何指针类型。除非先前指定,否则结果是实现定义的,可能未正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示。
如果它是陷阱表示,只是将指针传递给printf
具有未定义的行为。
此外,除了值0
之外,此类转换应通过强制转换来明确。
答案 2 :(得分:0)
您正在将p值设置为5。 * p将查找存储在地址5中的某些内容,这将导致分段错误。 p应指向有效的内存地址。
int a = 5;
int *p = &a;
printf("%d\n",*p ); //will print 5
printf("%p\n", p); //will print address of a -> &a