gpt4 book ai didi

c - 结构中的指针——未知大小的数组

转载 作者:太空狗 更新时间:2023-10-29 15:21:50 24 4
gpt4 key购买 nike

我正在尝试实现 TLV (Type-Length-Value)在 C 中,但是我在使值的动态大小正常工作方面遇到了问题。

我的结构是这样的:

typedef struct __attribute__((packed)){
unsigned char type;
unsigned char length;
unsigned char * value;
} TLV;

我正在尝试将数组转换为结构,以便我可以轻松访问类型和长度。例如一个数组:

unsigned char test[5] = {(unsigned char)'T', 0x03, 0x01, 0x02, 0x03};

其中数组中'T'为类型,第一个0x03为长度。

我像这样将数组转换为结构:

TLV* tlv = (TLV*)test; 

然而,当我尝试访问值数组时,我遇到了段错误,即使我尝试访问值内存地址的第一个元素(它应该是数组中长度之后的第一个元素)也是如此。

我怎样才能解决这个段错误?

最佳答案

value 不是数组,它是一个指针(指向结构之外的某处)。如果您想要数组(未知大小),请改为编写 unsigned char value[1]

typedef struct __attribute__((packed)) {
unsigned char type;
unsigned char length;
unsigned char value[1];
} TLV;

拥有一个大小为 1 的数组可以让您实际寻址任意数量的字节。这实际上是 UB,但它在我看到的所有情况下都实际使用并正常工作。

GCC 允许使用大小为 0 的数组。我已经习惯了这个约定,以至于我忘记了 C 中不允许使用大小为 0 的数组。

编辑:

长答案

数组和指针是有区别的。虽然您可以使用类似的代码来处理两者,但它们仍然是不同的东西。

免责声明:以下代码在 gcc 中有效,但可能不是严格有效的。我没有试图让它完全有效。

让我们定义两个结构:

typedef struct {
char p[20];
} sa;

typedef struct {
char *p;
} sp;

并创建这些实例:

sa x = { "Hello, world" };
sp y = { "Howdy, world" };

这两者有什么区别?

printf("%s\n", x.p); // prints "Hello, world"
printf("%s\n", y.p); // prints "Howdy, world"

这些地址呢?

printf("address of x = %p\n", &x); // On my machine it prints 0x7fffacce9b20
printf("address of y = %p\n", &y); // 0x7fffacce9b10

嗯.. 没什么特别的,除了这些数字.. 非常相似 - 两个结构位于大致相同的位置 - 在我的例子中它是堆栈,地址空间的末尾,但也可能在其他地方。

printf("address of x.p = %p\n", &x.p); // 0x7fffacce9b20
printf("address of y.p = %p\n", &y.p); // 0x7fffacce9b10

相同的数字。果然不出所料。

printf("address of x.p[0] = %p\n", &x.p[0]); // 0x7fffacce9b20 - same as before
printf("address of y.p[0] = %p\n", &y.p[0]); // 0x400764 - could be anything

现在这些都不一样了。字符串“Hello, world”与结构 x 位于同一位置,而字符串“Howdy, world”位于其他位置 - 数据段,地址空间开头的某个位置,但是,同样可能在其他位置。

所以这就是区别:数组是一些存储在“这里”的数据,而指针只是存储“某处”的数据的地址。

在您的情况下,您希望能够将数据保存在“此处”的某处 - 就在类型和长度之后。这就是您需要数组而不是指针的原因。

我找不到任何证据证明上面的 TLV 实现不是 UB,但我看到很多情况下,通过将字符数组转换为指向某个结构的指针来“解析”字符数组。我什至自己写了这样的代码。

0 维数组

正如我之前所说,C 标准不允许大小为 0 的数组。但它们是 GCC 允许的,这很方便,因为它允许您执行以下操作:

typedef struct {
unsigned char type;
unsigned char length;
unsigned char value[0];
} TLV;

int required_length = 10;
TLV *tlv = (TLV *) malloc(sizeof(TLV) + required_length);

如果没有大小为 0 的数组,您必须在上面代码的某处添加(或减去?我猜是减去)1。

关于c - 结构中的指针——未知大小的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27901380/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com