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

时间:2018-07-31 05:56:29

标签: c pointers casting 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[],我仍然遇到了细分错误。

3 个答案:

答案 0 :(得分:3)

这定义了一个指针变量

A* a;

它没有指向任何东西,指针未初始化。

这将访问它指向的任何内容

a->num = 1;
strcpy(a->arr, "Hi");

没有事先分配任何内容给指针(例如,使用malloc()),这是因为它调用的未定义行为可能会导致段错误。

答案 1 :(得分:1)

这是Yunnosch's answer的附录,可正确识别问题。假设您正确执行了操作,要么只写

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成员兼容的,但是请注意,由于允许编译器假设a和{{1} }指向不同的对象,因为它们的类型不兼容。有关更多信息,请阅读通常称为 strict别名规则的主题。

您还应该知道,不完整的数组类型(无大小)仅允许作为b的最后一个成员。像您这样的定义:

struct

成员typedef struct { int num; char arr[]; } B; 的大小是允许的,但是正确分配它是您的责任。 arrB)的大小不包含此成员。所以如果你只是写

sizeof(B)

您不能在B b; 中存储任何内容,它的大小为b.arr。最后一个成员称为 flexible array成员,并且只能与动态分配一起正确使用,并手动添加大小,如下所示:

0

这为您提供了一个实例B *b = malloc(sizeof *b + 64); ,其实例大小为*barr如果数组的类型不是char,则必须手动乘以成员类型的大小-char不必要,因为sizeof(char)的定义是1。因此,如果您将数组的类型更改为其他类型,例如int,您可以编写此代码以分配64个元素:

B *b = malloc(sizeof *b + 64 * sizeof *(b->arr));

答案 2 :(得分:0)

您似乎在混淆两个不同的主题。在C99 / C11中,char arr[];作为结构的最后一个成员是 Flexible Array Member (FAM),它允许您为结构本身和N个元素数量分配用于灵活的数组。但是,您必须为其分配存储空间。 FAM的好处是在通常需要两个分配的情况下允许一次分配和一次免费。 (在C89中,类似的实现被命名为 struct hack ,但略有不同)。

例如,B *b = malloc (sizeof *b + 64 * sizeof *b->arr);将为b plus 分配64个字符的存储空间,用于b->arr。然后,您可以使用正确的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

仔细检查一下,如果有帮助,请告诉我。如果您有其他问题,也请告诉我。您不清楚混乱的确切位置。