2

I am getting confused as to whether it is valid (in C) to pass a pointer to an array that has been initiated as follows (e.g. at compile time on the stack):

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

my_func(&a);


void my_func(int **a)
{
   int *tmp = *a; /* this statement fixes the problem */
   printf("%d %d %d", (*a)[0], (*a)[1], (*a)[2]); /*doesn't work */ 
   printf("%d %d %d", tmp[0], tmp[1], tmp[2]); /*does work */ 
}

when I step through this with gdb I can't 'see' any of the values (*a)[0], etc. from 'inside' my_func. e.g.

(gdb) p (*a)[0]
Cannot access memory at address 0x0

I'm thinking that possibly I have a fundamental misunderstanding with regard to what you can and can't do with arrays that are on the stack rather than the heap?

I hope thats not the case as it is very convenient for my unit tests to declare arrays on the stack as in the example, but I need to test functions that are expecting pointers to pointers to int.

Note I do get a compiler warning as follows:

 test_utility.c:499:5: warning: passing argument 1 of ‘int_array_unique’ from incompatible pointer type [enabled by default]
 ../src/glamdring2.h:152:5: note: expected ‘int **’ but argument is of type ‘int (*)[12]’

but I thought it would be ok to mix int *a[] with **a? Perhaps not? Are they not equivalent?

5
  • If you want to store the pointer on the stack you could cast it before storing it and cast it again when you want to use it: ptr_int = (int)ptr for storage of ptr_int and ptr = (int*)ptr_int for usage. But i'm not sure whether this is sufficient for your problem. Commented Dec 12, 2011 at 14:01
  • Is there a particular reason why you pass a reference to the array pointer? Commented Dec 12, 2011 at 14:04
  • @kenneth yes - i am using the parameter as both an input and return value. Commented Dec 12, 2011 at 14:07
  • I have a fix, needed an appropriate cast in my_func, int *tmp_a = *a; and everything starts working. Commented Dec 12, 2011 at 15:49
  • basically, I don't know my lvalues from my rvalues as pointed out by wildplasser. Hopefully rectifying that with some background reading Commented Dec 13, 2011 at 12:59

4 Answers 4

4

a[] is an array, not a pointer ("not an lvalue"); in your function call

func( &a);

&a decays to a pointer to int; &a is not a pointer to pointer to int. Why? there is no pointer to point to.

The function prototype

void func( int **p);

expects a pointer to pointer to int, that does not fit the function being called with a pointer to int as an argument, like you did.

UPDATE: I don't know what the OP's intentions were, so this is just a guess...

void my_func(int *a);

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

my_func(a); /* note: this is equivalent to my_func( &a ); */


void my_func(int *a)
{
   printf("%d %d %d\n", a[0], a[1], a[2] ); 
}
Sign up to request clarification or add additional context in comments.

11 Comments

Are you really sure &a is of type int*?
It is not a pointer to int, it decays into one. (because there is no pointer to point to, the pointer to array decays to pointer to 1st element)
Yes, of course I meant decaying. Well I didn't know that, but it makes perfect sense, since a pointer to the array is indeed a pointer to the first element. I never used &a anyway, so never really thought about it. +1.
@wildplasser I think you have probably provided the answer there but I can't understand it. Any chance you could illustrate your point with an example? e.g. bearing in mind what you have said, what code would be required to get it to work?
@wildplasser ok - so you can't pass in a pointer to a and then hope to dereference within the function to retrieve the array elements?
|
1
printf("%p vs %p vs %p\n",&a,&a[0],a); 

&a &a[0] and a - are all the same - the address of the first int in the array

void my_func(int **a);
int main(int ac, char *av[]) {
    int a[] = {1, 2, 3};
    int *p = a;
    printf("%p vs %p vs %p\n",&a,&a[0],a); //are all the same - the address of the first int in the array
    my_func(&p);
    return 0;
}
void my_func(int **a) {
    printf("%d %d %d", (*a)[0], (*a)[1], (*a)[2]);
}

http://www.ibiblio.org/pub/languages/fortran/append-c.html

http://publications.gbdirect.co.uk/c_book/chapter5/arrays_and_address_of.html

Comments

0

It's perfectly fine to declare an array on the stack and pass its address to a function, so long as the function doesn't try to store a reference to the array for later use.

Not sure why you're adding the extra indirection to the the argument, though. Why not just declare my_func to take an int* as a parameter, and simply pass a as the argument? This is less likely to confuse the debugger.

1 Comment

thats exactly what I thought. I can't understand why I can't dereference the pointer in gdb?
0

You are assuming that sizeof(int) == sizeof(void *). This might not be true. I am not sure if this is the cause of your problem, but at least I would start by either adding a runtime test asserting the assumption, or probably better change from int to pointer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.