为什么我得到一个"类型惩罚"即使使用`char *`时也会发出警告?

时间:2017-02-07 08:15:58

标签: gcc strict-aliasing

编译以下程序时

gcc(6.3.1 20170109)

#include <stdio.h>

int main(int argc, const char *argv[]) {
    unsigned char x[] = {0x66, 0x19};
    printf("%i\n", ((short *)((char *)&x[0]))[0]);
    return 0;
}

生成警告:

  

pun.c:在函数'main'中:   pun.c:5:5:警告:解除引用类型惩罚指针将破坏严格别名规则[-Wstrict-aliasing]

使用char指针时,是否不允许输入别名?

1 个答案:

答案 0 :(得分:4)

以下是C11(或至少是免费的N1570草案)对别名的评价:

  

对象的存储值只能由具有其中一个的左值表达式访问   以下类型:

     
      
  • 与对象的有效类型兼容的类型
  •   
  • 与对象的有效类型兼容的类型的限定版本,
  •   
  • 对应于有效类型的有符号或无符号类型的类型   对象,
  •   
  • 对应于合格版本的有符号或无符号类型的类型   有效的对象类型,
  •   
  • 聚合或联合类型,其中包含上述类型之一   成员(包括,递归地,子集合或包含的联合的成员),或
  •   
  • 字符类型。
  •   

字符类型异常意味着您可以通过char*unsigned char*访问任何类型,但这并不意味着您可以通过任何类型访问char*short*不符合char*此处列出的其他条件,因此此用法是未定义的行为。

另外,如果无条件允许,您可以打破对齐要求:

short x[] = {1, 2};
char* alias = x;
printf("%i\n", *(short*)&alias[1]);