假设k是指向C中整数的指针。
对于表达式** k,当我们尝试在赋值运算符(“ =”)的右侧对其求值时,该值是否非法?
这是我的想法:
** k实际上是*(* k)。当我们取消对k的引用时,我们得到一个整数值。然后,我们尝试取消引用整数,这是非法操作。
但是我的教科书说,右侧的这种表达实际上是合法的。
为什么呢?
答案 0 :(得分:5)
C 2018标准在第6.5.3.2节第2段中指出:“一元*
运算符的操作数应具有指针类型。”如果k
是指向整数的指针,则*k
是一个整数,不是指针类型,因此它不能是一元*
运算符的操作数。因此,诸如x = **k
之类的表达式违反了此规则。
第6.5.3.2 2条中的规则是一个约束,这意味着需要合格的编译器才能为其生成诊断消息,并且C标准未定义行为。
从技术上讲,C编译器除了发布诊断消息外,还可以接受表达式并根据需要进行定义。我不知道有谁这样做,而且没有普通的编译器这样做。
很有可能字符**k
可能会出现在较大的表达式中,而它们不能同时充当一元*
运算符,例如x = y**k
中的等效于{{1 }},其中第一个x = y * *k
是二进制乘法运算符。您应该显示课本中显示的精确文本。
答案 1 :(得分:0)
除了标准所说的以外,从根本上取消引用int毫无意义。假设编译器愿意假设int可以直接转换为指针(BIG假设)。编译器会假定它是哪种类型的指针?唯一安全的假设是void*
。并且取消引用void*
毫无意义,因为即使分配给已知类型,指针的类型仍然很重要:
unsigned int n = 0xFFFFFFFF;
void *pN = &n;
unsigned int fromIntPtr = *(unsigned int*)pN;
unsigned int fromCharPtr = *(unsigned char*)pN;
printf("%X\n", fromIntPtr);
printf("%X\n", fromCharPtr);
输出:
FFFFFFFF
FF
由于缺少一种指针,编译器可能可以根据LHS表达式来推断unsigned int*
。那是1)愚蠢的推论和2)C并没有真正推论类型。 (将类型化的RHS转换为不同类型的LHS值是不推断的:))