var和&(*var)之间有什么区别

SGa*_*tel 8 c language-lawyer

一些源代码使用符号&(*var),其中var已经是一个指针,喜欢int *var = ....

这两个符号之间有区别吗?

var != &(*var)吗?

示例:https://github.com/FreeFem/FreeFem-sources/blob/develop/src/medit/inout_popenbinaire.c#L40

chq*_*lie 10

&(*var)var在大多数情况下,在编译时进行评估,但请注意一些警告:

  • var应该是一个有效的指针,尽管编译器没有理由生成代码来取消引用它.实际上,C11指定&*var即使var是空指针也没有未定义的行为.
  • 正如Pascal Cuoq评论的那样,var不应该是指针void,但C标准明确地允许它用于这种情况......确实令人震惊.
  • 如果var是一个数组,与一个以上的元素,var并且&*var具有不同的类型和sizeof(var)sizeof(&(*var))具有不同的值:第一个是数组的大小而第二个是一个指向它的第一个元件的尺寸.
  • 正如Peter所评论的,如果var是一个未初始化的指针,那么评估var == &(*var)会给出未定义的行为(因为评估给定未定义行为的任​​何一方==- 访问未初始化变量的值是给出未定义行为的原因).

您在问题中链接到的示例使用此结构,无论如何:

#define WrdSiz 4

void getline_bin_float_vertex(int ddim, double *c, int *ref) {
    int i;
    float ff;

    for (i = 0; i < ddim; i++) {
        fread((unsigned char *)&(ff), WrdSiz, 1, stdin);
        c[i] = ff;
    }
    fread((unsigned char *)&(*ref), WrdSiz, 1, stdin);
}
Run Code Online (Sandbox Code Playgroud)

程序员正在从重定向到标准输入的文件中读取多个浮点值和一个整数.代码很笨拙且不可移植:

  • 大小float默认为4
  • 大小int是默默地认为是相同的4个字节
  • c必须是有效的指针,除非ddim是0
  • ref必须是一个有效的指针,因为它fread会尝试在它指向的地址存储4个字节,除非流位于文件末尾
  • 默认忽略文件结束和读取错误,并且可以进行未定义的行为.

代码可以通过这种方式简化和保护:

#define WrdSiz 4

/* read values from stdin, return non-zero in case of failure */
int getline_bin_float_vertex(int ddim, double *c, int *ref) {
    int i;
    float ff;

    assert(sizeof float == WrdSiz);
    assert(sizeof int == WrdSiz);
    assert(dim == 0 || c != NULL);
    assert(ref != NULL);

    for (i = 0; i < ddim; i++) {
        if (fread(&ff, sizeof ff, 1, stdin) != 1)
            return -1;
        c[i] = ff;
    }

    if (fread(ref, sizeof(*ref), 1, stdin) != 1)
        return -1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

此源代码的其他部分显示较差甚至无效的构造,您应该仅针对不应执行的操作的示例来学习此程序包.


Bas*_*tch 5

&(*var)当(指针变量)不包含旧版本C的有效地址时,可能有未定义的行为var.在这种情况下会感到害怕.但C11标准§6.5.3.2指出,编译器必须处理它等同于所有情况(包括当varNULL)

所以,var == &(*var)当是真的var包含有效的地址.当它包含其他内容(例如NULL)时,如果使用非C11符合的非优化编译器,它可能会崩溃(分段错误)(但是大多数编译器,即使是旧编译器,在这种情况下也不会生成一些崩溃代码)

但是编译器(甚至是旧C99之一)允许(在AS-如果规则),以优化 &(*var)var

  • 从C11(至少)开始,`&*E`在所有情况下都相当于`E`(包括`E`是一个空指针).见6.5.3.2/3 (2认同)