在这种情况下,为什么使用 memcpy 函数来更改 struct 中灵活数组的 dst 指针?

问题描述 投票:0回答:1
#include <cstring>
#include <cstdio>
#include <cstdlib>

struct Block {
    int32_t size;
    u_int8_t data[0];
};

int main(int argc, char **argv) {
    Block block;
    Block *ptr = &block;
    u_int8_t data_buffer[] = {1, 3, 0, 1, 3, 4, 5, 5, 6, 2, 2, 3};
    void *sdata = (void *)data_buffer;
    void *ndata = (void*)ptr->data;
    printf("data ptr: %p\n", ptr->data);      // 0x7ffe53275340
    printf("ndata: %p\n", ndata);             // 0x7ffe53275340
    memcpy((void*)ndata, &data_buffer, sizeof(void*));
    printf("ndata: %p\n", ndata);            // 0x505040301000301
    printf("*(&data_buffer): %p\n", *(&data_buffer)); // 0x7ffe53275330
    printf("data ptr: %p\n", ptr->data);     // 0x7ffe53275340
    for(int i{0}; i<12; i++) {
        printf("%d ", (((u_int8_t*)(ptr->data))[i]));
    }
    printf("\n");
    return 0;
}

代码块如上,

我很困惑,在memcpy函数之后,为什么ndata会变成0x505040301000301,一个如此奇怪的值?

我用谷歌搜索了灵活数组,但找不到确切的这种例子。 任何帮助将不胜感激。

c++ c c++11 memcpy flexible-array-member
1个回答
1
投票

具有灵活数组成员的结构体的大小不包括该成员的空间。 因此,如果您在堆栈上声明这样的结构,您实际上无法访问这些元素,因为它们不存在。 你正在做的是未定义的行为,因为你访问的内存超出了对象的边界。

您需要做的是声明一个指向该结构的指针,并为该结构以及所需数量的成员分配空间。

u_int8_t data_buffer[] = {1, 3, 0, 1, 3, 4, 5, 5, 6, 2, 2, 3};
struct Block *ptr = malloc(sizeof(struct Block) * sizeof(data_buffer));

还有:

  • 使用
    0
    作为数组大小是 GCC 扩展。 您应该将尺寸留空,这是符合 C 标准的方法。
  • 根据您使用的标头,此代码似乎是 C++,但在其他方面它看起来像 C 代码。 如果您确实想使用 C,请使用 C 标准头(即
    stdio.h
    而不是
    cstdio
    ),在声明结构时使用
    struct
    关键字,并编译为 C 程序。
© www.soinside.com 2019 - 2024. All rights reserved.