【问题标题】:Wrong values in Array containing Structs in C [duplicate]包含C中结构的数组中的错误值[重复]
【发布时间】:2018-06-24 04:35:39
【问题描述】:

我有这个结构:

(结构.h)

#pragma once

#ifndef STRUCT_H
#define STRUCT_H

typedef struct {
    unsigned int id;
    char *name;
    char *address;
} Struct;

#endif 

我创建了一个包含这些结构的动态数组。我还有一个循环将一些数据放入这些结构中:

(main.c)

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

int main() {

    int nStructs = 3;

    Struct *structArray = calloc(nStructs, sizeof * structArray);

    char input[30];

    for (int i = 0; i < nStructs; i++) {
        structArray[i].id = i;
        sprintf(input, "name_%d", i);
        structArray[i].name = input;
        sprintf(input, "addr_%d", i);
        structArray[i].address = input;
    }

    for (int i = 0; i < nStructs; i++) {
        printf("\n[%04d]    ID: %d\n", structArray[i].id, structArray[i].id);
        printf("[%04d]  NAME:   %s\n", structArray[i].id, structArray[i].name);
        printf("[%04d]  ADDR:   %s\n", structArray[i].id, structArray[i].address);
    }

    free(structArray);
    return 0;
}

当我尝试运行此代码时,“int ID”以正确的方式打印,但“char *name”和“char *address”都包含循环中的最后一个值(在本例中为“addr_3 "):

(输出)

[0000]  ID:     0
[0000]  NAME:   addr_2
[0000]  ADDR:   addr_2

[0001]  ID:     1
[0001]  NAME:   addr_2
[0001]  ADDR:   addr_2

[0002]  ID:     2
[0002]  NAME:   addr_2
[0002]  ADDR:   addr_2

我尝试在 Visual Studio 中使用调试器,当它们被放入数组(第一个 for 循环)时,这些值看起来没问题,但它们在某些时候会被覆盖。由于我是 Visual Studio 的新手,我不知道如何查看数组在特定点的值,而不仅仅是在值 [i] 处。

我在这里做错了什么?

编辑: 我从我的主项目中复制/粘贴了这段代码,所以只有我测试的部分才会出现在问题中。但我发现我忘了添加“free(structArray);”上面的'return 0;'。它现在添加到问题中,因此其他人不会犯同样的错误。

【问题讨论】:

  • 1) 为字符串分配空间。 2)实际复制数据给他们。

标签: c arrays visual-studio pointers struct


【解决方案1】:

几乎已经准备好一个示例,但后来我注意到了您的评论。

不,calloc 为您的结构分配空间,但不为字符串分配空间 - 您的结构只存储指针。

如果您不想更改结构,则应为每个字符串分配内存,然后将其复制,而不是在所有情况下都将指针存储到同一元素(在您的情况下,所有指针都指向input) . strdup 会为你做的:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "struct.h"

int main() {

    int nStructs = 3;

    Struct *structArray = calloc(nStructs, sizeof * structArray);

    char input[30];

    for (int i = 0; i < nStructs; i++) {
        structArray[i].id = i;
        sprintf(input, "name_%d", i);
        structArray[i].name = strdup(input);
        sprintf(input, "addr_%d", i);
        structArray[i].address = strdup(input);
    }

    for (int i = 0; i < nStructs; i++) {
        printf("\n[%04d]    ID: %d\n", structArray[i].id, structArray[i].id);
        printf("[%04d]  NAME:   %s\n", structArray[i].id, structArray[i].name);
        printf("[%04d]  ADDR:   %s\n", structArray[i].id, structArray[i].address);

        // Notice you now have to free those copies strings before your structs
        // go out of scope, or else you'll be leaking memory
        free(structArray[i].name);
        free(structArray[i].address);
    }

    return 0;
}

您可能想查看指针在 C/C++ 中的工作原理。

【讨论】:

  • strdup 可能不是现成的,但它本质上是一个 2 线,可以轻松实现。
  • 提到了 Visual Studio - 我在发布之前做了一个快速检查,它似乎对我可用。对于不可用的情况,您是对的..
  • "您可能想查看指针在 C/C++ 中的工作原理。"我是 C 新手,所以我会这样做。现在我更多地了解了内存如何与 calloc 以及与字符串一起使用的结构。生病阅读更多关于指针的内容。谢谢你的好答案。这对我帮助很大:)
【解决方案2】:

您需要使用 malloc 为结构中的所有字符串分配内存,或者将结构的定义更改为:

typedef struct {
    unsigned int id;
    char name[100];
    char address[100];
} Struct;

目前你的结构体中的所有字符指针都指向输入,因此输入改变了结构体中所有字符串的值。

要使您的代码在不更改结构定义的情况下正常工作,请执行以下类似操作:

for(int i = 0; i < nStructs; i++)
{
    structArray[i].name = malloc(100);
    structArray[i].address = malloc(100);
}

您可以在同一个 for 循环中执行此操作,并且只为每个字符串分配所需的内存。请务必检查 malloc() 是否返回 NULL。

【讨论】:

  • 我不想改变结构。如何为字符串分配内存?我的代码中不是用 calloc() 函数分配的内存吗?
  • structArray[i].name = input; -> structArray[i].name = malloc(strlen(input) + 1; strcpy(structArray[i].name, input);
  • 是的,一定要检查 malloc() 的返回是否为 NULL。
  • 别忘了释放这个新分配的内存,否则你会泄漏内存。
  • structArray[i].name = malloc(100) 非常非常难看。如果字符串短于 100,为什么要浪费内存?如果字符串长度超过 100,那你就不走运了。
猜你喜欢
  • 2021-07-15
  • 1970-01-01
  • 2013-05-06
  • 2022-01-10
  • 2012-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-19
相关资源
最近更新 更多