为什么printf会修改以前的局部变量? [重复]

问题描述 投票:-1回答:4

这个问题在这里已有答案:

我试图了解C行为并发现了一些奇怪的事情。我调试并发现表值是正确的,直到调用printf。我创建一个void函数来测试它是否是范围问题,但在调用此函数后,表值仍然保持正确。我现在想知道printf是否删除了以前的局部变量。

#include <stdio.h>
#include <stdlib.h>
void invertTable(int** tableau,int size){
    int temp[size];
    for(int i = 0; i < size; i++)
    {
        temp[i]=-1*tableau[0][i];
    }
    tableau[0]=temp;
}
void test(){

}
int main(int argc, char const *argv[])
{
    int* table=(int*)malloc(5*sizeof(int));
    table[0]=1;
    table[1]=2;
    table[2]=3;
    table[3]=4;
    table[4]=5;
    invertTable(&table,5);
    test();
    for(int i = 0; i < 5; i++)
    {
        //Here is the problem
        printf("\n %d \n",table[i]);
    }
    free(table);
    return 0;
}

预计-1 -2 -3 -4 -5

输出:-1 1962295758 1 1962550824 1962295741

c
4个回答
-1
投票

要获得正确的输出,您应该更改

int temp[size]int* temp = *tableauint* temp = (int*) malloc(sizeof(**table) * size)

这些解决方案的工作原理是因为*tableau和/或malloc分配的内存在invertTable之后没有被破坏。

通常temp应该在invertTable函数之后销毁并使tableau[0]成为悬空指针然后系统可以重新分配temp所指向的记忆。因此,这部分内存现在可能包含随机数据。这些数据可能是您执行程序时获得的数据。

我调试了你的代码,是的,调用printf时出现问题。对于那些不相信我的人,调试它并一步一步地观看tableau内容。我无法解释为什么所有这一切都发生在调用printf之后。在调用printf之前,tableau的内容确实是正确的。

我不确定,但这可能与heap有关。


2
投票

您的问题与printf无关,这是由于您的代码中的一个错误,您尝试使用您不应该使用的内存。

在你的invertTable函数的这一行:

 tableau[0]=temp;

您将main()函数中的table指针指向本地temp变量。

temp函数结束时,你的invertTable数组超出了范围,所以你最终得到一个悬空指针,你不能再使用那个内存 - 这样做是未定义的行为。

您可以改为动态分配内存,在invertTable结束后保持有效:

int *temp = malloc(sizeof(int) * size);
for(int i = 0; i < size; i++)
{
    temp[i]=-1*tableau[0][i];
}
//deallocate previous allocation
free(tableau[0]);
tableau[0]=temp;

0
投票

你的问题与printf无关,确实是invertTable,这是罪魁祸首。

处理数组时table等于&table[0]所以在这种情况下,你不需要发送tableau的地址。

#include <stdio.h>
#include <stdlib.h>
void invertTable(int *tableau,int size){
  for(int i = 0; i < size; i++)
    {
      tableau[i] = -1 * tableau[i];
    }
}
void test(){

}
int main(int argc, char const *argv[])
{
  int* table = (int*) malloc(5 * sizeof(int));
  table[0]=1;
  table[1]=2;
  table[2]=3;
  table[3]=4;
  table[4]=5;
  invertTable(table,5);
  test();
  for(int i = 0; i < 5; i++)
    {
      //Here is the problem
      printf("\n %d \n",table[i]);
    }
  free(table);
  return 0;
}

这将做你想要的。另外,您也不需要使用任何临时变量。

顺便说一句,temp是临时的,它没有在堆上分配,所以当invertTable返回时它被销毁。


0
投票
tableau[0]=temp;

这是无效的。这意味着返回指向本地数组的指针。这是未定义的行为。

你可以这样做:

for(int i = 0; i < size; i++)
    (*tableau)[i]*=-1;
© www.soinside.com 2019 - 2024. All rights reserved.