重新解释具有声明类型的对象的适当对齐指针

问题描述 投票:1回答:1

标准允许我们在适当对齐的情况下将对象类型的指针转​​换为彼此。 6.3.2.3(p7)

指向对象类型的指针可以转换为指向不同对象类型的指针。如果对于引用的类型,结果指针未正确对齐(68),则行为未定义。

标准允许我们将对象表示复制到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编译,那么这样的缓冲区对齐是否足够?

c language-lawyer type-punning
1个回答
2
投票

memcpy()看起来还不错。

c64_ptr -> value是UB。

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

- 与对象的有效类型兼容的类型,

- 与对象的有效类型兼容的类型的限定版本,

- 对应于对象的有效类型的有符号或无符号类型的类型,

- 对应于对象有效类型的限定版本的有符号或无符号类型,

- 聚合或联合类型,其成员中包含上述类型之一(包括递归地,子聚合或包含联合的成员),或者

- 角色类型。

在标准中查找compatible以完成图片。

© www.soinside.com 2019 - 2024. All rights reserved.