2010-07-16 140 views
0
?? fun() 
{ 
    int a[3]={3,3,4}; 
    return &a; 
} 

什么可能是兼容的返回类型。这里的指针指向3个整数的数组,而不仅仅是指向整数数组的指针。 目标是返回一个指向3个整数数组的指针。c语言。函数的返回类型

+3

更好的方法来做到这一点是具有的功能用一个指针指向数组作为参数,然后有功能填充阵列。 – FrustratedWithFormsDesigner 2010-07-16 14:24:15

+2

gcc甚至没有-Wall给出“警告:函数返回局部变量的地址” – Nyan 2010-07-16 14:31:18

回答

0

其他人都已经告诉你为什么你不应该这样做,因为它是写的,但这里有您感兴趣的类型。

给出一个声明int a[3],表达&a的类型是int (*)[3]int **),或“指针3元素数组INT的”,如

void f() 
{ 
    int a[3] = {1,2,3}; 
    int (*aptr)[3] = &a; 
    ... 
} 

以及用于返回该类型的函数的签名将int (*fun())[3] {...}

另外一个选择号没有显示是这样的:

int (*fun())[3] 
{ 
    int (*aptr)[3] = malloc(sizeof *aptr); 
    if (aptr) 
    { 
    (*aptr)[0] = 1; // array pointer must be deferenced before applying 
    (*aptr)[1] = 2; // the subscript. 
    (*aptr)[2] = 3; 
    } 
    return aptr; 
} 

虽然这不是非常有用的;你通常不会看到像这样分配单个固定大小的数组。稍微更有用被分配这些数组的数组:

int (*fun(size_t count))[3] 
{ 
    int (*aptr)[3] = malloc(sizeof *aptr * count); 
    if (aptr) 
    { 
    size_t i; 
    for (i = 0; i < count; i++) 
    { 
     aptr[i][0] = 1; // aptr[i] implicitly dereferences aptr, so 
     aptr[i][1] = 2; // there's no need for an explicit dereference 
     aptr[i][2] = 3; // here. 
    } 
    } 
    return aptr; 
} 

即使这样,如果有人需要分配一个固定大小的数组类型,他们通常隐藏一个typedef后面:

typedef int fixedSizeRecord[SOME_SIZE]; 
... 
fixedSizeRecord *fun(size_t count) 
{ 
    fixedSizeRecord *aptr = malloc(sizeof *aptr * count); 
    if (aptr) 
    { 
     // initialize contents as necessary 
     for (size_t i = 0; i < count; i++) 
     for (j = 0; j < sizeof *aptr/sizeof *aptr[0]; j++) 
      aptr[i][j] = ...; 
    } 
    return aptr; 
} 

抽象是一个的事。

我已经把这个表的几个迭代之前;你可能会发现它很方便。

 
Declaration: T a[N]; 

Expression  Type  Decays To  Value 
----------  ----  ---------  ----- 
     a  T [N]  T *    Address of first element in a 
     &a  T (*)[N] n/a    Address of a (same value as above, 
               but different type) 
     *a  T   n/a    Same as a[0] 
     a[i]  T   n/a    Value at index i 
    &a[i]  T *   n/a    Address of value at index i 
    sizeof a  size_t      Total number of bytes in a 
               (N * sizeof T) 
sizeof a/
    sizeof *a  size_t  n/a    Number of elements in a (N) 

Declaration: T a[N][M]; 

Expression  Type  Decays To  Value 
----------  ----  ---------  ----- 
     a  T [N][M] T (*)[M]   Address of first element in a[0] 
     &a  T (*)[N][M] n/a    Address of a (same value as above, 
               but different type) 
     *a  T [M]  T *    Same as a[0] 
     a[i]  T [M]  T *    Address of first element in array 
               at index i 
     &a[i]  T (*)[M] n/a    Address of array at index i (same 
               value as above, but different 
               type) 
     *a[i]  T   n/a    Same as a[i][0] 
    a[i][j]  T   n/a    Value at a[i][j] 
    &a[i][j]  T *   n/a    Address of value at index i,j 
    sizeof a  size_t  n/a    Total number of bytes in a 
               (N * M * sizeof T) 
sizeof a/
    sizeof *a  size_t  n/a    Number of subarrays in a (N) 
sizeof a[i]  size_t  n/a    Total number of bytes in a[i] 
               (M * sizeof T) 
sizeof a[i]/
    sizeof *a[i] size_t  n/a    Number of elements in a[i] (M) 
14

首先,你真的是应该不是返回一个局部变量的地址。当函数退出时,数组a将被破坏。

至于你的问题,&a的类型是int (*)[]

+0

我想多解释一下(*为什么* OP不应该返回地址局部变量,如果他们尝试会发生什么),它会*回答问题。 – FrustratedWithFormsDesigner 2010-07-16 14:46:09

+0

你是对的,但OP应该真的考虑到这一点。尽管如此,我仍然遵循你的建议并编辑我的答案。 – 2010-07-16 14:46:44

1

不要犯这个错误。只要fun()失去范围,所有它就是局部变量。

1

本地变量的地址不能从函数返回。 当地变量放在堆栈

3

的类型将是int **

但你的代码是错误的,因为你的表是在栈上。 从函数返回时,返回堆栈中元素的指针使得引用无处指向。

+2

该类型会衰减到int **,但它最初是一个指向3个整数数组的指针。 – 2010-07-16 14:28:10

+0

该类型不能是'int **';而_array_可能会衰减到一个指针,而指向array_的指针可能不会。 – 2010-07-16 14:35:11

+0

该类型将是指向10个整数数组的指针。 http://c-faq.com/aryptr/aryvsadr.html – Nyan 2010-07-16 14:40:57

0

如果你想返回一个指向数组的指针,不要返回局部变量的地址。你在这里返回的将是int**。你想要做的是分配一个新的int数组,并返回int*。你想要的可能是这样的:

int* fun() 
{ 
    int* a = malloc(sizeof(int) * 3); 
    a[0] = 3; 
    a[1] = 3; 
    a[2] = 4; 
    return a; 
} 

然后你需要确保以后释放分配的数组。

5

不要这样做。

您正在返回一个指向局部变量的指针。当函数返回时,该指针指向一个不再有效的位置,所以这个练习是毫无意义的。 返回类型本来int (*)[3]虽然,但是当你使用它作为函数的返回类型,其原型是int (*fun(void))[3](啊,EEW)

然而

如果a是静态的,你可以做

int (*fun(void))[3] 
{ 
    static int a[3]={3,3,4}; 
    return &a; 
} 

这是比较常见的指针数组中返回的第一个元素 - 但你必须在你可以访问3个指针的只有3个元素调用者“知道”。

int *fun(void) 
{ 
    static int a[3]={3,3,4}; 
    return &a[0]; // or just return a; 
} 

由于a在这些情况下静态的,你就不用担心实现相同的约reentrancy

2比较常见的方式:通过参数数组中

通行证并分配给呼叫者:

void fun(int *a) 
{ 
     a[0] = 3; 
     a[1] = 3; 
     a[2] = 4; 

} 

这样称呼它:

int a[3]; 
fun(a); 

动态分配内存:

int *fun(void) 
{ 
    int *a = malloc(3*sizeof *a); 
    if(a) { 
    a[0] = 3; 
    a[1] = 3; 
    a[2] = 4; 
    } 
    return a; 
} 

这样称呼它:

int *a; 
a = fun(); 
if(a) { 
    ///use a 
    free(a); // remember to free it when done 
} else { 
    //out of memory 
} 
+0

该标准是否确实保证返回一个指向本地作用域的静态变量的指针会没问题?我的意思是,我知道它是如何工作的,所以我无法想象它会如何爆炸。 – detly 2010-07-16 14:57:05

+0

@detly:除了重入以外,没有任何问题。 – 2010-07-16 14:59:23

0

你的功能将有int *返回类型,你会这样称呼:

int *array=fun(); 
printf("%d\n",array[0]); //print the first value in the array 

虽然!请记住,此函数正在返回对本地创建的变量的引用。不保证内存中的值在函数调用内部和后面都是相同的。你可能想要做更多的东西是这样的:

int *more_fun(){ 
    int *a=malloc(sizeof(int)*3); 
    a[0]=3; 
    a[1]=3; 
    a[2]=4; 
    return a; 
} 

这样称呼它:

int *array=more_fun(); 
printf("%d\n",array[0]); //print the first value in the array 

但是当你做,请务必free(array)这样你就不会泄露任何内存。

4

返回类型不会像其他人所建议的那样是int*int**。返回类型将是一个指向数组的指针。例如:

// we'll use a typedef so we can keep our sanity: 
typedef int(*int3arrayptr)[3]; 

int3arrayptr fun() 
{ 
    int a[3]={3,3,4}; 
    return &a; 
} 

虽然你可以一个返回指向一个局部变量,则不能使用这样的指针函数返回后,所以你不能使用的fun()返回值。

+0

除非我弄错了,否则你不能对返回的指针做任何事情(甚至不会增加或减少它)。 :) – 2010-07-16 14:42:04

+0

@Victor:你是对的;我在这句话的第二部分说“使用”,但是在第一部分中“解除”。我用“使用”来代替“取消引用”来澄清它。谢谢。 – 2010-07-16 14:50:03

1

a是一个局部变量。不要将指针返回给它。

回到正题。这是你如何定义一个指针到数组的大小-3型在C:

int a[3] = { 1, 2, 3 }; 

typedef int (*p_arr_3)[3]; 

p_arr_3 fun() { return &a; } 
0

如果你返回a,返回类型是int *。在这种情况下,我不完全确定&a的含义,而我的便捷参考告诉我可以应用于数组的唯一操作是sizeof,并且我没有Standard便捷。它可能被标记为非法,或者可能只是返回值aa表示的唯一东西就是数组,唯一像指向数组的指针是指向其第一个元素的指针。没有地址的地址。

在C中,很难传递数组,因为数组衰减为最轻微的挑衅指针。如果你需要传递一个实际的数组,最容易将它嵌入到struct中。包含int a[3];struct可作为常规值传递。

我假设你只是举一个例子,因为你返回一个局部变量的引用会导致各种不好的事情。在大多数实现中,该内存将用于下一个函数调用的其他事物,这意味着更改一个值会跺脚谁知道什么,并引用一个会得到谁知道什么。