在C中为整数指针赋值

时间:2017-09-17 17:32:42

标签: c pointers identifier

我对某些代码变体有些麻烦。

int *p = 5;
printf("%d\n", *p);

输出:SEGMENTATION FAULT

int *p = 5;
printf("%d\n", p);

输出:5

这里发生了什么?

3 个答案:

答案 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);解决了这个问题,但从intint *的隐式转换仍无法保证成功。此类代码仅用于非常特定的环境,例如嵌入式系统或操作系统。提高编译器警告级别可让编译器为此发出警告甚至错误(gcc -Wallclang -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