C 32位和64位之间的行为差异

C 32位和64位之间的行为差异,c,C,以下代码段在64位Ubuntu 14.04上执行,而在32位Ubuntu 14.04中出现seg错误。gcc版本在4.8.4(Ubuntu 4.8.4-2ubuntu1~14.04)中相同 #包括 主要() { int*a; int*b; *a=40; b=a; printf(“%x………%p………..%d\n”、*a、a、*a); } 在32位系统上,如果两个操作中的任何一个都完成,则相同的操作也会起作用- 注释掉b=a 添加a=malloc(sizeof(int))之前*a=40 有人能解

以下代码段在64位Ubuntu 14.04上执行,而在32位Ubuntu 14.04中出现seg错误。gcc版本在4.8.4(Ubuntu 4.8.4-2ubuntu1~14.04)中相同

#包括
主要()
{
int*a;
int*b;
*a=40;
b=a;
printf(“%x………%p………..%d\n”、*a、a、*a);
}
在32位系统上,如果两个操作中的任何一个都完成,则相同的操作也会起作用-

  • 注释掉b=a
  • 添加
    a=malloc(sizeof(int))之前*a=40
    
    有人能解释一下这一观察结果吗?这不是32位与64位的问题,而是使用不指向有效内存地址的指针的问题。在代码段中,您声明了指针
    *a
    *b
    ,但实际上没有将它们指向任何位置,从而导致未定义的行为

    使用指针时,总是立即分配足够的内存,或将它们指向现有的相应变量

    例如,所有后续语句都是有效的:

    int *a = NULL;
    int *b = malloc(sizeof(int));
    int c = 42;
    int *d = &c;
    
    通过不初始化它们,它们将指向任意位置<代码>*a=40
    可能是“偶然”为您工作的,因为它可能指向您当时可以访问的内存空间。但是,在一般情况下,此代码段应该在任一操作系统中产生一个分段错误

    如果您不打算将指针指向一个有效的内存地址,请考虑将其初始化为<代码> null ,以避免出现悬空指针。您永远不应该取消引用

    NULL
    指针,但在尝试这样做之前,您可以始终检查指针是否为
    NULL
    。例如:

    int *a = NULL;
    if ( a != NULL ) {
      *a = 42;
    }
    int *b = a;
    if ( b != NULL ) {
      printf("%d\n", *b);
    }
    
    此代码段不会打印任何内容,因为
    *a
    *b
    都将为
    NULL
    ,但您的代码不会产生分段错误

    值得一提的是,我在Debian 64位系统上也遇到了一个分段错误


    [编辑以集成@AnT、@tuple\u cat和@Weather Vane的反馈]

    原始代码具有未定义的行为。您没有为
    a
    分配有效的内存地址,因此它有一个随机地址。取消对它的引用,将40次写入分配给随机内存,以便任何事情都可以发生。
    malloc
    修复了错误,但是如果您不调用
    free(a)
    ,那么您就有了一个内存地址。将
    a
    分配给
    b
    不会更改任何此行为。打开编译器警告:警告C4700:未初始化的局部变量“a”已使用如果不添加2,则这是未定义的行为,因为您正试图写入未分配的内存。1不会更改任何内容,因为您没有在任何地方使用
    b
    int*a*a=40intc;int*a=&c
    从而获得有效的
    a
    *a
    。这里不需要涉及动态内存。“指针”的概念与动态内存没有任何联系。而且,
    malloc
    返回
    void*
    。就是这样。@AnT感谢您的反馈,我集成了它以使答案更通用:当使用指针时,它们应该指向有效的地方。@tuple_cat感谢您指出这条线索,我不知道这是不必要的。:)您能否添加一个解释,说明何时使用指针总是将其初始化为
    NULL
    ?取消引用
    NULL
    指针将不起作用。但是+1。
    int *a = NULL;
    if ( a != NULL ) {
      *a = 42;
    }
    int *b = a;
    if ( b != NULL ) {
      printf("%d\n", *b);
    }