[英]Copying char arr[64] to char arr[] can cause a segmentation fault?
typedef struct {
int num;
char arr[64];
} A;
typedef struct {
int num;
char arr[];
} B;
我宣布A* a;
然后将一些数据放入其中。 现在我想将其转换为B*
。
A* a;
a->num = 1;
strcpy(a->arr, "Hi");
B* b = (B*)a;
这是正确的吗?
有时(并非总是)出现细分错误,我想知道这是否可能是问题的原因。
即使转换后我没有尝试访问char arr[]
,也遇到了段错误。
这定义了一个指针变量
A* a;
它没有干净地指向任何东西,指针是未初始化的。
这将访问它所指向的内容
a->num = 1;
strcpy(a->arr, "Hi");
在没有事先分配任何内容给指针的情况下(例如使用malloc()
),这正在请求段错误,这是它调用的未定义行为的一种可能的结果。
这是Yunnosch答案的附录,可正确识别问题。 假设您正确执行操作,或者只写
A a;
当在函数中声明该对象时,它会为您提供一个自动存储期限的对象,或者您可以动态分配A
的实例,如下所示:
A *a = malloc(sizeof *a);
if (!a) return -1; // or whatever else to do in case of allocation error
然后,接下来是您的演员表:
B* b = (B*)a;
这是不正确的,类型A
和B
不兼容。 在这里,它可能会在实践中起作用,因为struct
成员是兼容的,但是请注意,由于编译器由于类型不兼容而允许a
和b
指向不同的对象,因此可能会发生奇怪的事情。 有关更多信息,请阅读通常称为严格别名规则的主题 。
您还应该知道,不完整的数组类型(无大小)仅允许作为struct
最后一个成员。 使用像您这样的定义:
typedef struct {
int num;
char arr[];
} B;
成员arr
可以有任意大小,但是正确分配它是您的责任 。 B
的大小( sizeof(B)
)不包括此成员。 所以如果你只是写
B b;
您不能在b.arr
存储任何 b.arr
,它的大小为0
。 最后一个成员称为灵活数组成员 ,只能与动态分配一起正确使用,并手动添加大小,如下所示:
B *b = malloc(sizeof *b + 64);
这将为您提供arr
大小为64的实例*b
。如果数组的类型不为char
,则必须手动乘以成员类型的大小-对于char
这是不必要的,因为sizeof(char)
为定义1
。 因此,如果将数组的类型更改为其他类型,例如int
,则可以编写此数组以分配64个元素:
B *b = malloc(sizeof *b + 64 * sizeof *(b->arr));
看来您在混淆两个不同的主题。 在C99 / C11中, char arr[];
由于结构的最后一个成员是灵活数组成员 (FAM),它允许您为结构本身分配数量,并为灵活数组分配N
个元素。 但是,您必须为其分配存储空间。 FAM的好处是在通常需要两个分配的情况下允许一次分配和一次免费。 (在C89中,类似的实现被命名为struct hack ,但略有不同)。
例如B *b = malloc (sizeof *b + 64 * sizeof *b->arr);
会为b
分配存储空间, 并为b->arr
分配64个字符的存储空间。 然后,您可以成员复制a
到b
使用正确的'.'
和'->'
语法。
一个简短的例子可以说明:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NCHAR 64 /* if you need a constant, #define one (or more) */
typedef struct {
int num;
char arr[NCHAR];
} A;
typedef struct {
int num;
char arr[]; /* flexible array member */
} B;
int main (void) {
A a = { 1, "Hi" };
B *b = malloc (sizeof *b + NCHAR * sizeof *b->arr);
if (!b) {
perror ("malloc-b");
return 1;
}
b->num = a.num;
strcpy (b->arr, a.arr);
printf ("b->num: %d\nb->arr: %s\n", b->num, b->arr);
free (b);
return 0;
}
使用/输出示例
$ ./bin/struct_fam
b->num: 1
b->arr: Hi
仔细检查一下,让我知道是否可以解决问题。 如果您有其他问题,也请告诉我。 您不清楚混淆的确切位置还不清楚。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.