malloc分配的内存中,将char*转换为其他指针类型是否违反严格别名规则?
你这个问题问到点子上了,先给你吃个定心丸:你的代码没有违反严格别名规则,而且你的核心理解是对的——malloc分配的内存确实是「无类型」的,和普通的int变量这种有确定类型的对象完全不同。
咱们先把严格别名规则的本质说清楚:它的核心是禁止用不兼容的指针类型去访问一个已经拥有「有效类型」的对象。什么是有效类型?简单说就是一块内存第一次被写入时,用来写入它的指针的类型(或者是被赋值对象的类型)。
那malloc的内存呢?它刚被分配出来的时候没有任何有效类型,相当于一张白纸,你用什么类型的指针去写它,就给对应的内存区域赋予了什么有效类型:
- 你用
unsigned char* ptr给*ptr赋值10,那ptr指向的这个字节的有效类型就是unsigned char; - 你用
(double*)(ptr + 1)给这块区域赋值3.14,那从ptr+1开始的8个字节的有效类型就变成了double; - 同理,ptr+9开始的8个字节,被写入
double值后,有效类型也是double。
后续你用对应的类型去读取这些区域,完全符合规则:比如用unsigned char*读第一个字节(char类型允许别名任何类型,这是规则的例外),用double*读后面的两个double区域(和它们的有效类型完全匹配)。
再对比你提到的反例:如果是一个int变量,它从诞生起就有确定的有效类型int,这时候你用char*指向它再转成double*去访问,就违反了严格别名规则——因为你在用和原有有效类型不兼容的指针去访问它,而这不属于规则允许的例外情况。
这里要额外提一个小坑:你的代码里把double存在ptr + 1的位置,很多系统中double需要8字节对齐的内存地址(比如地址是8的倍数),ptr + 1的地址大概率不满足对齐要求,这时候虽然不违反严格别名,但会触发未定义行为(可能程序崩溃,也可能运行但性能极差)。gcc没警告你是因为默认情况下它不会检查对齐问题,但这不代表没问题,实际写代码的时候要注意内存对齐的要求。
总结一下:你的例子完全符合C标准的规则,没有违反严格别名,放心用,但对齐问题要留意。
备注:内容来源于stack exchange,提问作者user22903339

