将char*转换为void**后进行读写操作在C语言中是否合法?
C语言中字符指针转换为
void**后读写的合法性问题 问题背景
给定以下C代码:
char * bufPtr = ...; // 指向一个剩余至少sizeof(void *)个字符的char数组 void *ptr1 = ...; void *ptr2;
假设bufPtr已正确对齐,请问以下两行代码是否合法?
*(void **)bufPtr = ptr1; // (1) ptr2 = *(void **)bufPtr; // (2)
已知char *可以别名任意类型,但不确定这种允许是否适用于反向情况——即把char*转换为其他类型指针后进行读写操作。
更新:代码库基于C语言,优先关注C语言下的结论,原本以为C和C++规则类似,可能存在误解。
结论与解释
这两行代码在C标准下是合法且行为定义良好的,前提是bufPtr满足对齐要求(题目已明确该前提),具体原因如下:
C标准的类型别名与对象表示规则
C标准允许使用char*访问任何对象的字节表示,同时也允许在足够大且正确对齐的字符数组存储区域中,通过写入其他类型的对象表示来“创建”该类型的对象,后续通过对应类型的指针访问这个对象是合法的。对两行代码的具体分析
- 代码(1):将
bufPtr转换为void**后解引用赋值,本质是把ptr1的二进制表示(即void*类型的对象表示)写入到bufPtr指向的字符数组区域。由于数组剩余空间足够容纳void*的大小,且bufPtr对齐正确,这个操作符合标准,不会触发未定义行为。 - 代码(2):通过
void**读取之前写入的内容并赋值给ptr2,本质是读取void*类型的对象表示并还原为void*值,行为完全定义良好。
- 代码(1):将
与C++的差异
C++的类型系统规则更严格,这种直接将char*转换为其他类型指针并读写的操作可能会触发未定义行为,但C标准明确允许这种用法,二者在这一点上确实存在差异。
内容的提问来源于stack exchange,提问作者Joshua Green
相关产品推荐
相关产品推荐

