为什么printf会修改以前的局部变量?

时间:2019-04-08 09:14:32

标签: c

我试图了解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

4 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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返回时它被销毁了。

答案 2 :(得分:0)

tableau[0]=temp;

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

您可以这样做:

for(int i = 0; i < size; i++)
    (*tableau)[i]*=-1;

答案 3 :(得分:-1)

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

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

这些解决方案之所以起作用,是因为*tableau之后malloc和/或invertTable分配的内存没有被破坏。

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

我调试了您的代码,是的,调用printf时出现问题。对于那些不相信我的人,请对其进行调试并逐步查看tableau的内容。 我无法解释为什么仅在调用printf之后才发生所有这些情况。在调用printf之前,tableau的内容确实正确。

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