【问题标题】:C pointers: Assignment from incompatible pointer typeC 指针:来自不兼容指针类型的赋值
【发布时间】:2019-08-09 08:37:21
【问题描述】:

当我用 gcc 7.3.0 编译这段代码时,我得到一个“来自不兼容指针类型的赋值”。

int intVar = 1;
char* charPointer;

charPointer = &intVar;
printf("%d", *charPointer);

到目前为止一切顺利。我可以通过这种方式进行指针分配来处理它:

charPointer = (char*)&intVar;

现在我的疑问是:第二种情况有何不同?如果我不将 charPointer 转换为 int* 时,我仍然会搞砸,例如将它增加 n 或取消引用它。那么为什么编译器在这两种情况下的行为不同呢?他为什么要关心分配期间指针类型是否不匹配?我只是想了解它背后的逻辑。

【问题讨论】:

  • 第二种情况也不例外。您只是明确地告诉编译器“将此指针转换为char *”,而没有转换,不清楚它是故意的还是潜在的错误。区别在于一个编译,另一个不编译。

标签: c pointers gcc gcc-warning


【解决方案1】:

由于 int * 到 char * 的随意类型更改,编译器会警告潜在的陷阱。通过强制转换,编译器假定编码人员知道他们在做什么。


在 C 语言中,各种类型的指针可以存在于不同的位置,具有不同的大小并以不同的方式编码。

所有对象指针(int*、char *、struct foo *)共享相同的大小和编码是很常见的,但一般来说,这不是必需的。

函数指针的大小与对象指针不同的情况并不少见。

char * 和void * 共享相同的大小和编码,并且字符指针指向具有最小对齐要求的数据。将非char* 对象指针转换为char * 总是“工作”。反过来并不总是正确的。导致未定义的行为 (UB)。

转换为非字符指针也有抗锯齿的风险(编译器需要跟踪通过一种指针类型的数据更改反映在另一种指针类型中)。可能会导致非常奇怪的未定义行为。> 更好的代码可以避免指针类型更改1,并且在需要时通过强制转换显式。


1 例外情况包括将对象指针更改为void * 或在没有对齐问题的情况下形成void*。

【讨论】:

    【解决方案2】:

    指针转换有点危险。

    如果您转换的指针类型与目标类型没有充分对齐,那么您在转换时就已经获得了 UB(==未定义的行为;请阅读它是什么,除非您已经这样做了)。

    否则,如果由于 C 的 strict aliasing rules 要求您通过与其有效类型充分兼容的左值类型访问对象,您通常会在取消引用时获得 UB。

    虽然最后一段并不完全适用于 char 指针的转换,因为 char 指针可以为任何类型起别名,但警告(编译器也可能使其成为硬错误)仍然有用,因为转换仍然有点危险。

    printf("%d", *(char*)&(int){0xFFFF});
    

    只会得到第一个字节(它取决于字节顺序是最重要的还是最不重要的),打印 255(如果实现的 char 类型是无符号的)或 -1(如果它是有符号的)。

    printf("%d", *&(int){0xFFFF});
    

    将为您获取int 中的所有字节。

    如果编译器允许您从 int * 分配给 char * 并仅发出警告,则它的行为应该与强制转换相同,但您确实需要强制强制转换才能使 C 符合(以及编译器对转换保持沉默)。

    【讨论】:

    • "打印 255(如果实现的 char 类型是无符号的)或 -1(如果它是有符号的)。 --> 根据字节序导致不同的结果。
    【解决方案3】:

    正如@Mike Holt 所说,实际上并没有什么不同,只是你告诉编译器“别担心,我是要这样做的”。

    编译器确实会担心,因为分配给不同类型的指针通常不是您想要做的。您的代码告诉编译器“将持有此变量的内存视为持有不同类型的变量”。这几乎可以肯定是特定于平台的行为,并且可能是未定义的行为,具体取决于类型。

    【讨论】:

    • 编译器确实担心,因为标准规定它必须输出诊断信息。
    猜你喜欢
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 2019-06-05
    • 2014-07-27
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 2019-06-09
    相关资源
    最近更新 更多