&(*var)
在大多数情况下与var
的结果相同,但请注意以下一些限制:
var
应该是一个有效的指针,尽管编译器不需要生成解引用它的代码。实际上,C11规范规定,即使var
是一个空指针,&*var
也不会出现未定义的行为。
- 正如所评论的那样,
var
不应该是一个指向void
的指针,但C标准明确允许这种情况...令人震惊。
- 如果
var
是一个具有多个元素的数组,则var
和&*var
具有不同的类型,而sizeof(var)
和sizeof(&(*var))
具有不同的值:前者是数组的大小,后者是指向其第一个元素的指针的大小。
- 如所评论的那样,如果
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);
}
程序员正在从重定向到标准输入的文件中读取一些浮点值和一个整数。代码很麻烦,不可移植:
float
的大小被默默地假定为 4。
int
的大小被默默地假定为相同的 4 个字节。
- 除非
ddim
为 0,否则 c
必须是有效指针。
fread
将尝试在其指向的地址处存储 4 字节,除非流已到达文件末尾,否则 ref
必须是有效指针。
- 文件结束和读取错误被默默忽略,可能导致未定义行为。
通过下面的方法可以简化代码并使其更加安全:
#define WrdSiz 4
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;
}
此源代码的其他部分显示出较差甚至无效的结构,您应该仅研究此软件包以了解不应该做什么的示例。
&(*var)
wherevar
is already a pointer, likeint *var = ...
*” 这个比较我不理解。我看不到“like”后面有任何&
符号。 - alkfread( (unsigned char *)&(OBJECT)
,尽管为什么他们认为这是一个好主意是任何人都无法猜测的。我会说这是一种不好的模式,因为它具有冗余的(在C89中有害的)强制转换。该代码还有其他的问题,比如#define WrdSiz 4
、没有包含stdio.h
,以及while (!feof(stdin))
等等。基本上,这是一个充满错误和未定义行为的可怕代码,您不应将其视为学习材料。 - M.M