如果适当对齐,则Standard允许我们将指向对象类型的指针彼此强制转换。 6.3.2.3(p7)
:
指向对象类型的指针可能会转换为指向对象类型的指针 不同的对象类型。如果结果指针不正确 对于引用类型,该行为是不确定的。
该标准允许我们将对象表示形式复制到char[sizeof(the_object_type)]
6.2.6.1(p4)
:
可以将值复制到unsigned char [n]类型的对象中 (例如,通过memcpy);所得的字节集称为对象 值的表示形式。
此外,标准明确指出
具有相同对象表示形式的两个值(NaN除外) 比较相等,但是比较相等的值可能具有不同的对象 表示形式。
考虑以下代码:
struct contains_64_t{
uint64_t value;
};
int main(int args, const char *argv[]){
_Alignas(struct contains_64_t)
char buf_2_64t[2 * sizeof(struct contains_64_t)];
struct contains_64_t c64_1;
c64_1.value = 1;
struct contains_64_t c64_2;
c64_2.value = 2;
memcpy(buf_2_64t, &c64_1, sizeof(c64_1));
memcpy(buf_2_64t + sizeof(c64_1), &c64_2, sizeof(c64_2));
//suitably aligned, ok
struct contains_64_t *c64_ptr = (struct contains_64_t*) buf_2_64t;
printf("Value %"PRIu64"\n", c64_ptr -> value);
}
问题: 编写这样的代码是否很必要?如果没有,这样做会遇到什么样的问题?
据我所见
我们可以将char*
强制转换为struct contains_64_t
,因为它已适当对齐。但是问题在于,buf
的声明类型为char[2 * sizeof(struct contains_64_t)]
。因此,从形式上讲,我们无法通过类型为buf
的左值访问struct contains_64_t *
。
但这很奇怪,因为我们有适当对齐的指针和字面上相同的对象表示形式。当然我们可以声明struct contains_64_t buf[2];
,但是如果struct
包含 可变长度数组
UPD:如果我们假设要使用GCC进行编译,那么进行这种缓冲区对齐就足够了吗?
答案 0 :(得分:2)
memcpy()
看起来不错。
c64_ptr -> value
是UB。
一个对象的存储值只能由左值访问 具有以下类型之一的表达式:
-与对象的有效类型兼容的类型,
-与有效类型兼容的合格版本 对象
-一种类型,它是与 对象的有效类型,
-一种类型,它是对应于a的有符号或无符号类型 有效类型的对象的限定版本,
-包含上述类型之一的集合或联合类型 其成员之间的类型(包括,递归地, 子集合或包含的并集),或
-字符类型。
在标准中查找compatible
以完成图片。