C语言 动态内存分配和指针

8ftvxx2r  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(176)

我在纠结指针和它们的分配。我想知道我的分配是否正确,否则应该怎么做。另外,我得到了关于fgets和puts函数的警告,但我认为这与错误的分配有关。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. const int n = 30, m = 30;
  6. struct employer {
  7. char *name[3][1];
  8. char *pass[n][m];
  9. int *ID;
  10. };
  11. int main() {
  12. struct employer admin;
  13. i = 0;
  14. for (i = 0; i < 3; i++) {
  15. admin.name[i][1] = (char*)calloc(1, n);
  16. }
  17. for (i = 0; i < 3; i++) {
  18. fgets(admin.name[i][1], n, stdin);
  19. puts(admin.name[i][1]);
  20. }
  21. return 0;
  22. }

以下是我得到的警告:

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

它们分别与I分配的线路、fgets fcn线路和puts fcn线路有关。你能告诉我我错在哪里吗?

ckocjqey

ckocjqey1#

代码的三个问题。首先,您在main中使用了i,但没有声明它。第二,您正在访问长度为1的数组中的索引1。由于数组是从0开始索引的,所以应该使用索引0。第三,C中数组的维数必须是常量表达式。因此,我将const int声明替换为预处理器指令来定义NM

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #define N 30
  6. #define M 30
  7. struct employer {
  8. char *name[3][1];
  9. char *pass[N][M];
  10. int *ID;
  11. };
  12. int main(void) {
  13. struct employer admin;
  14. size_t i = 0;
  15. for (i = 0; i < 3; i++) {
  16. admin.name[i][0] = (char*)calloc(1, N);
  17. }
  18. for (i = 0; i < 3; i++) {
  19. fgets(admin.name[i][0], N, stdin);
  20. puts(admin.name[i][0]);
  21. }
  22. return 0;
  23. }

这是值得怀疑的,为什么你会想要一个长度为1的数组。这不会让你得到任何简单的char *name[3]

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #define N 30
  6. #define M 30
  7. struct employer {
  8. char *name[3];
  9. char *pass[N][M];
  10. int *ID;
  11. };
  12. int main(void) {
  13. struct employer admin;
  14. size_t i = 0;
  15. for (i = 0; i < 3; i++) {
  16. admin.name[i] = (char*)calloc(1, N);
  17. }
  18. for (i = 0; i < 3; i++) {
  19. fgets(admin.name[i], N, stdin);
  20. puts(admin.name[i]);
  21. }
  22. return 0;
  23. }

在实践中,您应该在假设分配成功之前检查分配是否成功。
您还需要free动态分配的任何内存。对于这样一个小程序,很可能你运行的操作系统会在程序停止时自动释放内存,但这并不是一个坏习惯。
当然,对于这样一个已知数组边界的简单程序,是否真的需要动态分配是值得怀疑的。

展开查看全部
xwbd5t1u

xwbd5t1u2#

我得到了关于fgets和puts函数的警告,但我认为这与错误的分配有关。
不,它与动态内存分配无关
char *name[3][1];只有一列。
您尝试在使用索引1时访问第二

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

**C *(和 C++)索引从0开始

要访问第一列,您需要:

  1. admin.name[i][0]

以下不是有效的C

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

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

还有这个:

  1. int main() {
  2. struct employer admin;
  3. i = 0;

不会编译。您需要定义i

  1. int i = 0;

另外在C语言中不强制转换结果的malloc家族函数。记住释放已分配的内存!!!

展开查看全部

相关问题