在C

时间:2016-01-12 13:10:09

标签: c pointers

当我编写以下代码时,我正在学习C中的指针:

#include <stdio.h>
main()
{
    char *p = 0;
    *p = 'a';
    printf("value in pointer p is %c\n", *p);
}

编译代码时,编译成功。虽然,当我执行其out文件时,发生了一个小时错误:Segmentation Fault (core dumped)

我无法理解为什么会发生运行时错误。毕竟,指针p指向字符a,因此输出应该是a

虽然,当我编写以下代码时,它已成功编译并运行:

#include <stdio.h>
main ()
{
    char *p = 0;
    char output = 'a';
    p = &output;
    printf("value which pointer p points is %c\n", *p);
}

有人可以解释为什么第一个程序失败,而第二个程序成功运行?

3 个答案:

答案 0 :(得分:11)

您的代码会调用未定义的行为,因为您要取消引用NULL 1 指针。指针需要指向有效的内存,这是实现你想要的一个简单的方法

#include <stdio.h>

int // `main()' MUST return `int'
main(void)
{
    char *pointer;
    char value;

    pointer = &value; // Now the pointer points to valid memory
    *pointer = 'a';

    printf("value in pointer p is %c\n", *pointer);
    return 0;
}
  

1    6.3.2.3指针

     
      
  1. 值为0的整型常量表达式,或者类型为void *的表达式,称为空指针常量。 66)如果将空指针常量转换为指针类型,则保证将结果指针(称为空指针)与指向任何对象或函数的指针进行比较。
  2.               

    66) NULL (和其他标题)中定义为空指针常量;见7.19。

         

    6.5.3.2地址和间接运营商

         

    <强>语义

         
        
    1. 一元*运算符表示间接。如果操作数指向函数,则结果是函数指示符;如果它指向一个对象,则结果是指定该对象的左值。如果操作数的类型为''指向类型'',则结果的类型为''type''。如果为指针指定了无效值,则unary *运算符的行为未定义。 102)
    2.               

      102) 因此,&*E相当于E(即使E是空指针),&(E1[E2])((E1)+(E2))。如果E是函数指示符或左值是一元&运算符的有效操作数,则总是如此,*&E是函数指示符或左值等于E。如果*P是左值而T是对象指针类型的名称,则*(T)P左值,其类型与T点的类型兼容

           

      由一元*运算符取消引用指针的无效值中有一个空指针,一个地址与指向的对象类型不对齐,以及一个对象的地址结束后它的一生。

答案 1 :(得分:1)

在第一个示例中,您将p设置为0,这在大多数实现中与NULL相同。然后尝试取消引用该指针(读/写p指向的内存位置),这将导致核心转储。 p 指向字符a。这个*p = 'a'表示“获取p指向的内存位置并将a放在那里”。

在第二个示例中,您将p设置为output的地址,因此它指向已知的内存位置。然后,当您取消引用时,您正在读取p点所在位置的值,即output。这是有效的用法。

答案 2 :(得分:1)

指针是&#34;特殊&#34;存储另一个变量地址的变量。看看这个程序,我希望它能帮助你弄清楚指针是什么以及如何使用它:

#include <stdio.h>

int main(void){

        int x = 10, *pointer = 0;

        pointer = &x;

        printf("\nThe address of x : %p.\n", &x);
        printf("\nThe address of the  pointer : %p.\n", pointer);

        printf("\nThe value of x : %d.\n", x);

        *pointer += 10;

        printf("\nThe value of x after we modifed it with the pointer : %d.\n\n", x);

return 0;

}

如果你编译并给这个程序一个运行,这将是它的输出:

x的地址:0xbf912108。

指针的地址:0xbf912108。

x的值:10。

我们用指针修改它后的x的值:20。

您可以清楚地看到指针的地址与变量本身相同。这就是为什么当你修改指针时(例如在我的程序中我做*pointer += 10)它实际上修改了变量。