2015-05-07 2 views
7
#include <stdio.h> 
#include <stdlib.h> 

struct Point { 
    double x; 
}; 

void test(struct Point **a, int len) 
{ 
    int i; 

    printf("a = %p\n", a); 
    for (i = 0; i < len; ++i) 
     printf("%f\n", a[i]->x); 
} 

int main() 
{ 
    int i; 
    int len = 4; 

    struct Point *P; 

    P = malloc(len*sizeof(struct Point)); 

    for (i = 0; i < len; ++i) { 
     P[i].x = i; 
     printf("%f\n", P[i].x); 
    } 
    printf("&P = %p\n", &P); 
    test(&P, len); 

    return 0; 
} 

Я пытаюсь передать массив структур в функцию (я хочу передать указатель на массив, а не сделать копию). Когда я пытаюсь использовать массив внутри функции, я получаю нарушение доступа. Каков правильный способ сделать это? Что я делаю не так? a == &P, поэтому он должен работать, не так ли?Ошибка при передаче указателя на массив структур

+1

Но 'P' уже * есть * указатель, он указывает на первый элемент выделенной памяти (массив). Передавая указатель, как и вы, вы не копируете ничего, кроме фактического указателя. –

+5

'printf ("% f \ n ", (* a) [i] .x);' – BLUEPIXY

ответ

5

Почему вы хотите struct Point **? Вы можете переписать так же, как

void test(struct Point *a, int len) 
{ 
    //some stuff 
    printf("%f\n", a[i].x); 

} 

и назвать его как

test(P, len); 

Таким образом, ИМХО, требование

Я хочу передать указатель на массив

также встречается #.


(#) Примечание: Для того, чтобы быть строгим, здесь мы проходим указатель на первый элемент массива, однако, поведение сравнивает равны. Спасибо г-ну @alk за комментарий.

+0

Спасибо, Итак, чтобы убедиться, что в функции нет копии, и любые изменения, которые я делаю в массиве, сохраняются после возвращения функции? – user1801359

+0

To nitpick: передается указатель на 1-й элемент массива. Это отличается от указателя на массив, последним будет 'struct Point (* pa) [len]'. – alk

+0

@alk Очень верно, сэр. Можете ли вы предложить соответствующие формулировки, чтобы изменить мой ответ? –

3

Передача &p функционировать test означает, что вы передаете указатель на первый элемент массива один элемент типа struct Point *. Следовательно, действует только a[0] (и, следовательно, a[0]->x), а все остальные a[i] не имеют доступа. Это вызовет неопределенное поведение.

a[i]->xa[0][i].x или (*a)[i].x в test функция.

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

+2

Или '(* a) [i] -> x' –

+3

или лучше' (* a) [i] .x ' –

+2

@WojciechFrohmberg, разве это не должно быть то, что предложил Йоахим Пилеборг в вышеупомянутом комментарии? –

1

Массив следует передавать с использованием параметра struct Point *a. Когда вы увеличиваете a, указатель перемещается на sizeof(struct Point).

void test(const struct Point *a, int len) 
{ 
    ... 
} 
1

Другие ответы предлагают вам лучше alternatives.But я положу это здесь, чтобы помочь всем (я) понять, почему это неправильно.

enter image description here

0

Я хочу передать указатель на массив,

Принимая ваши требования в буквальном смысле вы делаете это так:

void test(size_t len, struct Point (*a)[len]) 
{ 
    size_t i; 

    printf("a = %p\n", (void *) a); 

    for (i = 0; i < len; ++i) 
    printf("%f\n", (*a)[i].x); 
} 

И называть это так:

size_t len = 4; 
struct Point * p = malloc(len * sizeof *p); 

for (i = 0; i < len; ++i) { 
    p[i].x = i; 
    printf("%f\n", p[i].x); 
} 

printf("p = %p\n", (void *) p); 
printf("&p = %p\n", (void *) &p); 

test(len, &p); 

Вы также можете реализовать то же самое функциональность (зацикливание по элементам массива) путем перехода по пути, предложенному Sourav Ghoshanswer. Затем вы передадите указатель на элемент массива 1 st, но указатель на сам массив.

+0

Уже исправлено. @hacce Спасибо, во всяком случае. – alk

Смежные вопросы