动态内存分配和指针

Dynamic memory allocation and pointers

提问人:DM10 提问时间:9/9/2023 最后编辑:ChrisDM10 更新时间:9/9/2023 访问量:112

问:

我正在为指针及其分配而苦苦挣扎。 我想知道我是否正确分配,否则应该如何完成。 此外,我收到有关 fgets 和 put 函数的警告,但我认为这与错误的分配有关。

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

const int n = 30, m = 30;

struct employer { 
    char *name[3][1];
    char *pass[n][m];
    int *ID;
};

int main() {
    struct employer admin;
    i = 0;
    for (i = 0; i < 3; i++) {
        admin.name[i][1] = (char*)calloc(1, n); 
    }
 
    for (i = 0; i < 3; i++) {
        fgets(admin.name[i][1], n, stdin);
        puts(admin.name[i][1]);
    }
 
    return 0;
}

以下是我收到的警告:

  • 数组索引 1 已超过数组(包含 1 个元素)的末尾 [-Warray-bounds]“;
  • 数组索引 1 已超过数组(包含 1 个元素)的末尾 [-Warray-bounds]“;
  • 数组索引 1 已超过数组(包含 1 个元素)的末尾 [-Warray-bounds]“;

它们与我分配的线、fgets fcn 线和放置 fcn 线分别相关。 你能告诉我我哪里错了吗?

C 指针 struct dynamic-memory-allocation fgets

评论

2赞 dbush 9/9/2023
数组索引从 0 开始。
0赞 Chris 9/9/2023
只包含一个字符指针的数组有什么意义?
0赞 Chris 9/9/2023
在你已经分配但未声明它。maini
0赞 0___________ 9/9/2023
它不是 C 语言。

答:

0赞 Chris 9/9/2023 #1

代码的三个问题。首先,您已经使用但未声明它。其次,您正在对 length 为 的数组中的索引进行寻址。由于数组是从 开始的,因此您应该使用 index 。第三,C 语言中数组的维度必须是常量表达式。因此,我已将您的声明替换为预处理器指令来定义 和 。imain1100const intNM

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

#define N 30
#define M 30

struct employer { 
    char *name[3][1];
    char *pass[N][M];
    int *ID;
};

int main(void) {
    struct employer admin;
    size_t i = 0;
    for (i = 0; i < 3; i++) {
        admin.name[i][0] = (char*)calloc(1, N); 
    }
 
    for (i = 0; i < 3; i++) {
        fgets(admin.name[i][0], N, stdin);
        puts(admin.name[i][0]);
    }
 
    return 0;
}

为什么需要长度为 1 的数组是值得怀疑的。这让你一无所获.char *name[3]

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

#define N 30
#define M 30

struct employer { 
    char *name[3];
    char *pass[N][M];
    int *ID;
};

int main(void) {
    struct employer admin;
    size_t i = 0;
    for (i = 0; i < 3; i++) {
        admin.name[i] = (char*)calloc(1, N); 
    }
 
    for (i = 0; i < 3; i++) {
        fgets(admin.name[i], N, stdin);
        puts(admin.name[i]);
    }
 
    return 0;
}

在实践中,您应该检查您的分配是否成功,然后再假设它已成功。

您还需要动态分配的任何内存。对于这样一个小程序,您正在运行的操作系统可能会在程序停止时自动释放内存,但这并不是一个坏习惯。free

当然,对于这样一个已知数组边界的琐碎程序,是否真的需要动态分配是值得怀疑的。

评论

0赞 Chris 9/9/2023
是的,它编译干净,没有警告使用 .-Wall -Wextra
0赞 Chris 9/9/2023
我正在使用 GCC,但我现在看到错误。
0赞 0___________ 9/9/2023
如果 N 是常量表达式,那么 有什么意义呢?malloc
0赞 Chris 9/9/2023
事实上。我唯一能看到的一点是,每次将其中一个结构传递给函数时,都不想复制 90 个字符。当然,它已经复制了 900 个由成员提供的字符指针。pass
0赞 0___________ 9/9/2023
为什么要按值传递它们?
0赞 0___________ 9/9/2023 #2

我收到有关 fgets 和 put 函数的警告,但我认为是 与错误分配有关。

否,它与动态内存分配无关

char *name[3][1];只有一列。

您尝试在使用索引时访问第二1

admin.name[i][1]
              ^
              |---------- here

C(和 C++)中的索引从0

要访问第一列,您需要:

admin.name[i][0]

以下内容无效。C

它是带有 GCC 扩展的 C++,如果您使用 C 语言编译器,它将无法编译。

struct employer { 
    char *name[3][1];
    char *pass[n][m];
    int *ID;
};

还有这个:

int main() {
    struct employer admin;
    i = 0;

不会编译。您需要定义i

int i = 0;

同样在 C 语言中,不要强制转换族函数的结果。请记住释放分配的内存!!malloc

评论

0赞 Chris 9/9/2023
还有C++和许多其他语言。花一些时间习惯这一点会得到回报。
0赞 0___________ 9/9/2023
请@Chris详细说明
0赞 Chris 9/9/2023
不是针对你的。只是强调这一点的重要性。