【问题标题】:Content of array pointer is altered outside the loop数组指针的内容在循环外被改变
【发布时间】:2022-01-04 13:35:56
【问题描述】:

我在函数内部初始化数组指针的值,首先分配它,然后在读取值时迭代分配它的内容(结构指针)。

这些是Richiesta的定义和初始化函数的内容:

    typedef struct richiesta {
        int durata;
    } *Richiesta;

    void leggiParametri(Richiesta **richieste, int *n){
        // size
        scanf("%d", n);

        *richieste = calloc(*n, sizeof(struct richiesta));

        //printf("Inside loop:\n");
        for(int i = 0; i < *n; i++){
            Richiesta richiesta = malloc(sizeof(struct richiesta));
            printf("%d\t", richiesta);
            scanf("%d", &richiesta->durata);
            (*richieste)[i] = richiesta;
            printf("%d: %d\n", i, (*richieste)[i]->durata);
        }
        printf("Outside loop:\n");
        printf("%d: %d\n", 0, (*richieste)[0]->durata);
        printf("%d: %d\n", 1, (*richieste)[1]->durata);
    }

main 正文:

    Richiesta *richieste = NULL;
    int n = -1;
    leggiParametri(&richieste, &n);

给出以下输入:

6
4
7
3
8
1
5
15

输出是:

-858131760  0: 4
-858127616  1: 7
-858127584  2: 3
-858127552  3: 8
-858127520  4: 1
-858127488  5: 5
Outside loop:
0: -858127520
1: 7

问题仅出现在数组的第一个元素上,在for 循环中它包含读取的正确值,而在外部它包含特定值,该值对应于第 5 个元素指向的地址(打印为一个整数)。 (即使在其他函数或主体中打印数组内容也会发生同样的事情)

  • 是什么导致了问题?
  • 为什么它指向那个特定的值?
  • 有什么方法可以让它发挥作用吗?

此外,取消注释printf("Inside loop:\n"); 行会在打印时返回分段错误。

【问题讨论】:

  • 这是什么 Richiesta richiesta = malloc(sizeof(struct richiesta));?!
  • Richiesta 是一个自定义 typedef,一个指向结构 richiesta 的指针,因此分配了堆中所需的空间@VladfromMoscow
  • 代码没有意义。您没有在此语句中分配指针数组 *richieste = calloc(*n, sizeof(struct richiesta));
  • 旁注:当使用多个指针变量从函数返回多个值时,请使用临时变量,并且只在函数末尾分配给您的指针。这样您就不必一直遵循变量,并且更容易处理可能的错误情况。现在你到处都有*n(*richieste),这使得代码更难阅读。
  • 请注意代码不能遗漏重要信息,struct richiestaRichiesta 的定义都是这样的。请创建minimal reproducible example 并删除不相关的东西,如变量t

标签: arrays c struct dynamic-memory-allocation typedef


【解决方案1】:

您没有在此语句中分配指针数组

*richieste = calloc(*n, sizeof(struct richiesta));

您在评论中所写的类型说明符Richiestastruct richiesta 类型的别名。你分配了一个结构数组。

所以这个作业

(*richieste)[i] = richiesta;

没有意义。

看来你的意思

*richieste = calloc(*n, sizeof( Richiesta ));

注意对这样的指针使用 typedef

typedef struct richiesta *Richiesta;

是个坏主意。这只会让代码的读者感到困惑。

【讨论】:

  • 是的,你确实是对的,我已经标记了答案,但我有完全相同的代码结构和相同的“错误”,但别名定义不同,可以正常工作,所以我不相信错误是与您的评论相关
【解决方案2】:

你被结构体和指向结构体的指针所吸引。分配一个指针数组以便稍后为每个元素分配一个结构是一种反模式,正确的方法确实是直接分配一个结构数组。但随后代码会变成:

void leggiParametri(Richiesta* richieste, int* n, int* t) {
    // dimensione
    scanf("%d", n);
    //printf("%d\n", *n);
    *richieste = calloc(*n, sizeof(struct richiesta));

    // richieste
    //printf("Inside loop:\n");
    for (int i = 0; i < *n; i++) {
        Richiesta richiesta = *richieste + i;
        printf("%p\t", richiesta);
        scanf("%d", &(richiesta->durata));
        printf("%d: %d\n", i, (*richieste)[i].durata);
    }
    printf("Outside loop:\n");
    printf("%d: %d\n", 0, (*richieste)[0].durata);
    printf("%d: %d\n", 1, (*richieste)[1].durata);

    // tempo
    scanf("%d", t);
    //printf("%d\n", *t);
}

你可以这样调用函数:

Richiesta richieste = NULL;
int n, t;
leggiParametri(&richieste, &n, &t);
// other processing....
free(richieste);

【讨论】:

    【解决方案3】:
    1. 不要将指针隐藏在typedefs 后面。这是一种非常糟糕的做法。
    2. 不要使用没有特殊需要的副作用。你只分配一维数组,你应该使用函数返回值。
    typedef struct Richiesta
    {
        int durata;
    } Richiesta;
    
    Richiesta *leggiParametri(int *n)
    {
        Richiesta *richiesta = NULL;
        // size
        if(scanf("%d", n) != 1) { /*error handling */};
    
        if(n >= 0)
        {
            richiesta = calloc(*n, sizeof(*richiesta));
            //printf("Inside loop:\n");
            for(int i = 0; i < *n; i++)
            {
                scanf("%d", &richiesta[i].durata);
                printf("%d: %d\n", i, richiesta[i].durata);
            }
            printf("Outside loop:\n");
            printf("%d: %d\n", 0, richiesta[0].durata);
            printf("%d: %d\n", 1, richiesta[1].durata);
        }
        return richiesta;
    }
    ``
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 1970-01-01
      • 2013-05-20
      相关资源
      最近更新 更多