开发者

c language. Return type of a function

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

what could be the com开发者_如何学Cpatible return type. Here the pointer is pointing to the array of 3 integers not just the pointer which points to integer array. Aim is to return a pointer to array of 3 integers.


First, you really should not return the address of a local variable. When the function exits, the array a will get destroyed.

As for your question, the type of &a is int (*)[].


Don't do this.

You are returning a pointer to a local variable. When the function returns, that pointer points to a location that's no longer valid, so this exercise is pointless. The return type would have been int (*)[3] though, but when you use that as a return type of a function, the prototype would be int (*fun(void))[3] (ugh, eew)

However

If a was static, you could do

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

It's more common to return a pointer to the first element in an array - though you'll have to "know" in the caller that you can access 3 and only 3 elements of that pointer.

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

Since a is static in these cases, you'll have to worry about reentrancy

2 more common ways of achieving the same:

Pass in the array through the parameters and allocate it in the caller:

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

}

Call it like:

int a[3];
fun(a);

Dynamically allocate the memory:

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

Call it like:

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


The return type would not be an int* or int** as others have suggested. The return type would be a pointer to an array. For example:

// 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; 
}

While you can return a pointer to a local variable, you cannot use such a pointer after the function returns, so you cannot use the return value of fun().


The type would be int**

But your code is wrong because your table is on the stack. Returning the pointer of an element in the stack make the reference pointing in nowhere when returning from the function.


Don't make the mistake. As soon as fun() loses scope, so does all it's local variables.


The address of a local variable cannot be returned from a function. Local variables are placed in the stack


a is a local variable. Don't return a pointer to it.

Back to the point. This is how you define a pointer-to-array-of-size-3 type in C:

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

typedef int (*p_arr_3)[3];   

p_arr_3 fun() { return &a; }


Everyone else has already told you why you shouldn't do this as it is written, but here are the types you are interested in.

Given a declaration int a[3], the type of the expression &a is int (*)[3] (not int **), or "pointer to 3-element array of int", such as

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

and the signature for a function returning that type would be int (*fun())[3] {...}.

One other option nos didn't show is this:

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;
}

although this isn't terribly useful; you don't normally see allocations of single, fixed-size arrays like this. Somewhat more useful is allocating an array of those arrays:

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;
}

Even so, if somebody needs to allocate a fixed-size array type, they usually hide it behind a 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;
}

Abstraction is a good thing.

I've put up several iterations of this table before; you might find it handy.

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)


If you want to return a pointer to an array, don't return the address of local variables. What you are returning here would be int**. What you want to do is allocate a new array of int, and return int*. What you want is probably something like:

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

You then need to make sure to free the allocated array later.


Your function would have a return type of int * and you would call it like this:

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

Although! Keep in mind that this function is returning a reference to a locally created variable. There is no guarantee that the value in memory will be the same between inside and after the function call. You probably want to do something more like this:

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

Call it like:

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

But when you're done, make sure to free(array) so you don't leak any memory.


If you were to return a, the return type would be int *. I'm not entirely sure what &a means in this case, and my handy reference tells me that the only operation that can be applied to an array is sizeof, and I don't have the Standard handy. It may be flagged as illegal, or it may just return the value of a. The only thing a denotes is the array, and the only thing like a pointer to an array is a pointer to its first element. There is no address of the address.

In C, it's hard to pass around an array, since arrays decay to pointers on the slightest provocation. If you need to pass around an actual array, it's easiest to embed it in a struct. A struct containing int a[3]; can be passed around as a regular value.

I assume that you were just giving an example, because you're returning a reference to a local variable leads to all sorts of bad things. In most implementations, that memory will be used for other things with the next function call, which means that changing a value will stomp on who-knows-what, and referencing one will get who-knows-what.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜