我目前正在try 分配一个未知大小的 struct .我知道下面的方法是可行的,但我的问题是,如果我事先不知道"Num"的大小,我如何执行下面的方法?当我try 用malloc和大小2直接分配*num时,它不允许我访问num[0]num[1],就像我能够对int数组指针所做的那样.

我知道,如果我不使用 struct ,我可以做到以上几点.例如,int *A加上malloc(10*(sizeof(int *)),我可以同时访问a[0]a[5].对于 struct ,我似乎无法做到这一点,但我可能只是做错了什么.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
char word[50];
} test;

int main(void)
{
    test *num[2];
    num[0]=(test *)malloc(3*sizeof(test *));
    num[1]=(test *)malloc(3*sizeof(test *));
    strcpy(num[0]->word, "hello");
    strcpy(num[1]->word, "... you");
    puts(num[0]->word);
    puts(num[1]->word);
}

推荐答案

一般情况下:

sizeof (test *)(指针的大小)不能保证等于(即,这里肯定小于)sizeof (test)(指针points to的大小;这里是 struct 的大小).

在我的机器上

#include <stdio.h>

typedef struct {
    char word[50];
} test;

int main(void)
{
    printf("sizeof (test) = %zu\n", sizeof (test));
    printf("sizeof (test *) = %zu\n", sizeof (test *));
}

sizeof (test) = 50
sizeof (test *) = 8

short分配意味着将没有足够的内存来表示 struct 成员,并且当您耗尽所述内存时,将没有定义的行为.您似乎遇到了问题,并试图通过将每个分配的大小增加三倍来解决这些问题,如示例所示.如果您想要指向三个连续 struct 的指针,这仍然是一个不正确的内存量,但是足够的内存将一个小字符串(例如,strlen(str) < 3 * sizeof (test *))复制到这些 struct 中的第一个不太可能导致问题(即,段错误).

在你用int秒的测试中,同样的错误不太可能引起任何人的注意.再一次,在我的机器上

#include <stdio.h>

int main(void)
{
    printf("sizeof (int) = %zu\n", sizeof (int));
    printf("sizeof (int *) = %zu\n", sizeof (int *));
}

sizeof (int) = 4
sizeof (int *) = 8

在最坏的情况下,使用sizeof (int *)字节来存储int对象很可能是内存的过度分配,甚至可能是盈亏平衡.如果你很好奇,你可以判断你的机器,但这并不是特别重要--如果你在正确的表达式上使用sizeof,你就会有正确的内存量.

其一般形式为

T *foo = malloc(sizeof *foo); // equivalent: sizeof (T)

其中分配的是存储对象本身所需的字节数(不是指向所述对象的指针).如果指针值将分配给数组中的元素,则不会更改.

T *bar[3];
bar[0] = malloc(sizeof *bar[0]); // equivalent: sizeof (T)

对于更具体的问题,可以重新表述为

如何分配一个可能需要改变大小的数组?

答案是从乐观的或其他默认长度开始,并分配足够的内存到malloc(或calloc;如果开始长度为零,则从NULL指针值开始).当空间需求发生变化时,将数组大小调整为realloc.

这里是一个任意的例子,grows一个数组,一次一个元素.

#include <stdio.h>
#include <stdlib.h>

struct line {
    char buf[64];
};

int main(void)
{
    size_t length = 0;
    struct line *lines = NULL;

    struct line current;

    while (1) {
        printf("> ");

        if (!fgets(current.buf, sizeof current.buf, stdin))
            break;

        void *mem = realloc(lines, sizeof *lines * (length + 1));

        if (!mem) {
            fputs("Out of memory.\n", stderr);
            return 1;
        }

        lines = mem;
        lines[length++] = current;
    }

    putchar('\n');

    for (size_t i = 0; i < length; i++)
        fputs(lines[i].buf, stdout);

    free(lines);
}
> hello
> world
> 
hello
world

C++相关问答推荐

为什么静态说明符为内联函数生成外部定义?

将 typewriter LF打印到Windows终端,而不是隐含的CR+LF

显式地将值转换为它从函数返回的类型的含义是什么?

使用额外的公共参数自定义printf

LibpCap禁用监视器模式(C、MacOS)

判断X宏的空性

在WSL关闭/重新启动后,是什么原因导致共享对象依赖关系发生更改?

从uint8_t*转换为char*可接受

是否需要包括<;errno.h>;才能使用perror?

将返回的char*设置为S在函数中定义的字符串文字可能会产生什么问题?

关于scanf()和空格的问题

获取前2个连续1比特的索引的有效方法

为什么GCC 13没有显示正确的二进制表示法?

Malloc和对齐

可以对两种 struct 类型中的任何一种进行操作的C函数

如果类型是新的,offsetof是否与typeof一起工作?

访问未对齐联合的成员是否为未定义行为,即使被访问的成员已充分对齐?

尽管将其标记为易失性,但 gcc 是否优化了我的等待代码?

使用fread()函数读取txt文件

Makefile - 将 .o 文件放入子文件夹中