定义函数内数组指针

问题描述:

我不明白为什么ARR没有指向我已在功能测试中取得的数组:定义函数内数组指针

void test(int *arr) 
{ 
    int tmp[] = {2,4}; 
    arr = tmp; 
    printf("%d %d\n",arr[0],arr[1]); 
} 

int main() 
{ 
    int *arr; 
    test(arr); 
    printf("%d %d\n",arr[0],arr[1]); 
    return 0; 
} 

当我运行这个程序我:

2 4 
17744 786764 

arr是指针,为什么不更新值?

更新: 我现在看到我误解了很多关于指针和函数本地变量的问题。已经更新我的小笨笨的脚本,以适用的东西:

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

void test(int *arr){ 
    arr[0] = 123; 
    arr[1] = 321; 

    printf("%d %d\n",arr[0],arr[1]); 
} 

int main() 
{ 
    int arr[2]; 
    test(arr); 
    printf("%d %d\n",arr[0],arr[1]); 
    return 0; 
} 
+0

因为你是按值传递指针 - 所以你只能改变它在你的'test'功能的本地副本... – dragosht

+0

以及如何将arr'的''在副本main'得到更新? –

它因为在C中的参数通过值传递。 arr您正在通过main只是复制到功能参数arr
作业arr = tmp;使arr指向新位置。 现在arr指向一个自动局部变量,并且一旦函数达到其结尾就不会存在。
因此,在main

printf("%d %d\n",arr[0],arr[1]); 

的语句调用未定义的行为。

你的函数改为

void test(int **arr) // Change parameter to pointer to pointer to int 
{ 
    int *tmp = malloc(2*sizeof(int)); // Allocate memory dynamically 
    tmp[0] = 2; 
    tmp[1] = 4; 
    *arr = tmp; 
    printf("%d %d\n", (*arr)[0], (*arr)[1]); 
}  

main称呼其为

test(&arr); 

这是因为在C参数通过值通过,这意味着它们的值复制和功能只有副本。修改副本当然不会修改原始内容。在main函数中,当test返回时变量仍将未初始化,导致未定义行为当您试图对其进行解引用时。

C没有通过引用,但它可以使用指针进行仿真。在你的情况下,你必须传递一个指针指向指针。

但是,这并不是全部,你尝试设置指向一个局部变量的指针,局部变量,以及本地。它们的生命周期在函数返回时结束,并且一旦函数返回,指向它们的指针就不会有效。

有两种方法可以解决这两个问题。第一个问题是通过使用地址的操作者将指针传递到指针解决,即

test(&arr); 

test功能必须相应地修改以处理指针指向int

第二个问题可以通过几种方法解决。最简单的方法是延长变量的生命周期,以便即使在函数返回后,它也会继续生存。基本上只有两种方法:将变量设置为全局变量,或将其设置为局部变量static。解决第二个问题的另一种方法是使用malloc动态分配数组,但是一旦完成了该操作,您就必须记住free以避免内存泄漏。

您通过值传递指针(C已仅由值通过),即指针的副本被创建指向整数数组。因此,有在指针的初始值没有变化在main

如果你愿意,你需要传递指针的地址,但在这种情况下,也访问它在main也会造成问题,因为tmp是一个局部变量,其范围将只保持有限的功能test

所以在main当您尝试打印指针的内容(这是未初始化)将调用未定义行为

  1. 参数按值传递。因此,您只修改副本,而不是实际参数。要真正修改main中的arg,请使用指向指针的指针。
    定义你的函数是这样的:

    void test(int** arr) 
    

    ,并取消对它的引用的函数从main修改arr。此外,呼叫test这样,而不是:

    test(&arr); 
    
  2. 自动变量超出范围的功能已经恢复,并给他们的任何进一步的访问是不确定的行为。这意味着使用main中的数组也是未定义的。
    为了防止这种情况,你可以使阵列static

    static int tmp[] = { 0, 2 }; 
    

    就这样,tmp初始化只一次存在在整个运行,因此不未定义的行为。