我正在尝试在结构中分配 char
数组值并检索数据,但在检索时遇到一些问题。
struct first {
int a;
int b;
};
struct second {
int c;
int d;
struct first * f_t[2];
};
int main()
{
struct second *p;
char a[24] = {1, 0, 0, 0,
2, 0, 0, 0,
3, 0, 0, 0,
4, 0, 0, 0,
5, 0, 0, 0,
6, 0, 0, 0};
p = (struct second *)a;
p->f_t[0] = (struct first *) (a + 8);
p->f_t[1] = (struct first *) (a + 16);
printf("%d %d %d %d %d %d",
p->c, p->d, p->f_t[0]->a, p->f_t[0]->b, p->f_t[1]->a, p->f_t[1]->b);
}
输出:
1 2 1245008 1245016 1245024 6
前两个值正确(1
和 2
),但其余的似乎是一些垃圾值。
请帮助识别一些错误的初始化或其他相同的方法。
最佳答案
首先,永远不要假设结构中的填充。它的工作相当可靠,但技术上是未定义的行为。
更重要的是,您违反了严格的别名规则。编译器假设您永远不会使用不同类型的指针(在本例中为 struct first*
和 char*
)访问同一内存位置。您可以使用 -fno-strict-aliasing 来解决这个问题,或者使用 union 来进行类型双关,就像通常所说的那样。去 here了解更多信息。
此代码的更正确版本是 -
#include <stdio.h>
#include <stdlib.h>
#include <alloca.h>
#include <string.h>
struct first {
int a;
int b;
};
struct second {
int c;
int d;
struct first * f_t[2];
};
int main()
{
struct second *p;
char a[24] = {1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,6,0,0,0};
p = alloca(sizeof(struct second));
memset(p, 0, sizeof(struct second));
memcpy(p, a, sizeof(int)*2);
p->f_t[0]= alloca(sizeof(struct first));
p->f_t[1]= alloca(sizeof(struct first));
memset(p->f_t[1], 0, sizeof(struct first));
memset(p->f_t[0], 0, sizeof(struct first));
memcpy(p->f_t[0], a + 8, sizeof(struct first));
memcpy(p->f_t[1], a + 16, sizeof(struct first));
printf("%d %d %d %d %d %d",p->c,p->d,p->f_t[0]->a,p->f_t[0]->b,p->f_t[1]->a,p->f_t[1]->b);
}
注意:使用 alloca()
是不好的做法。除非您知道自己在做什么,否则不要使用它。在这里很好,因为它只是在堆栈上分配的一个小结构,但通常远离它并使用 malloc()
或仅使用局部变量。
这在技术上仍然属于未定义的行为,因为我们假设结构如何填充,这是特定于实现的,但大多数平台使用自对齐数据类型,并且在使用正确对齐的结构时速度要快得多,因此很容易猜测。欲了解更多信息,请访问here 。 我仍然强烈建议不要这样做,因为这是未定义的行为,而且很容易搞砸。
此外,下次请确保提供最小、完整且可编译的示例。
关于c - 访问结构体内部的结构体指针数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51671823/