C передает указатель на массив в стеке - PullRequest
1 голос
/ 12 декабря 2011

Я запутался в том, допустимо ли (в C) передавать указатель на массив, который был инициирован следующим образом (например, во время компиляции в стеке):

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

когда я делаю это с помощью gdb, я не могу «увидеть» ни одно из значений (* a) [0] и т. Д. Изнутри my_func. например,

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

Я думаю, что, возможно, у меня есть фундаментальное недопонимание относительно того, что вы можете и не можете делать с массивами, которые находятся в стеке, а не в куче?

Я надеюсь, что это не так, поскольку мои модульные тесты очень удобны для объявления массивов в стеке, как в примере, но мне нужно протестировать функции, которые ожидают указатели на указатели на int.

Заметьте, я получаю предупреждение компилятора следующим образом:

 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]’

но я думал, что будет хорошо смешать int *a[] с **a? Возможно нет? Разве они не эквивалентны?

Ответы [ 4 ]

4 голосов
/ 12 декабря 2011

a [] - это массив, а не указатель («не lvalue»);в вашем вызове функции

func( &a);

& распадается на указатель на int;& a не указатель на указатель на int.Зачем? нет указателя , на который можно указать.

Прототип функции

void func( int **p);

ожидает указатель на указатель на int, который не соответствует функции, вызываемой с помощьюуказатель на int в качестве аргумента, как вы сделали.

ОБНОВЛЕНИЕ: Я не знаю, каковы были намерения ОП, так что это всего лишь предположение ...

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] ); 
}
1 голос
/ 12 декабря 2011
printf("%p vs %p vs %p\n",&a,&a[0],a); 

& a & a [0] и a - одинаковы - адрес первого целого в массиве

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

0 голосов
/ 12 декабря 2011

Вы предполагаете, что sizeof(int) == sizeof(void *). Это не может быть правдой. Я не уверен, является ли это причиной вашей проблемы, но, по крайней мере, я бы начал с добавления теста времени выполнения, подтверждающего это предположение, или, возможно, лучше изменил бы с int на указатель.

0 голосов
/ 12 декабря 2011

Прекрасно объявить массив в стеке и передать его адрес функции, если функция не пытается сохранить ссылку на массив для дальнейшего использования.

Не уверен, почему вы добавляете дополнительную косвенность к аргументу.Почему бы просто не объявить my_func, чтобы принять int* в качестве параметра, и просто передать a в качестве аргумента?Это менее вероятно, чтобы запутать отладчик.

...