繁体   English   中英

将char arr [64]复制到char arr []会导致分段错误吗?

[英]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;

这是不正确的,类型AB不兼容。 在这里,它可能会在实践中起作用,因为struct成员兼容的,但是请注意,由于编译器由于类型不兼容而允许ab指向不同的对象,因此可能会发生奇怪的事情。 有关更多信息,请阅读通常称为严格别名规则的主题

您还应该知道,不完整的数组类型(无大小)仅允许作为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个字符的存储空间。 然后,您可以成员复制ab使用正确的'.' '->'语法。

一个简短的例子可以说明:

#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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM