2017-01-17 2 views
2

принять в виду следующий фрагмент кода:указатель на структуру Pass по ссылке в C

#include <stdio.h> 
#include <stdlib.h> 

typedef struct 
{ 
    int a; 
    int b; 
    int c; 
}A; 

A *test; 

void init(A* a) 
{ 
    a->a = 3; 
    a->b = 2; 
    a->c = 1; 
} 
int main() 
{ 
    test = malloc(sizeof(A)); 
    init(test); 
    printf("%d\n", test->a); 
    return 0; 
} 

Он прекрасно работает! Теперь представьте, что я хочу использовать функцию malloc вне самого main, не возвращая указатель на struct. Я бы поставил malloc внутри init и проехал test адрес. Но это, похоже, не работает.

#include <stdio.h> 
#include <stdlib.h> 

typedef struct 
{ 
    int a; 
    int b; 
    int c; 
}A; 

A *test; 

void init(A** a) 
{ 
    *a = malloc(sizeof(A)); 
    *a->a = 3; 
    *a->b = 2; 
    *a->c = 1; 
} 
int main() 
{ 
    init(&test); 
    printf("%d\n", test->a); 
    return 0; 
} 

Он продолжает говорить мне, что Int a (или b/c) не является членом struct A, когда я использую указатель.

+0

Держу пари, это не то, что он говорит вам. Каково фактическое сообщение об ошибке? – melpomene

+0

@melpomene запрос для члена 'a' в чем-то не структуре или союзе – Primemaster

+2

См.? Он даже не упоминает 'struct A'. В нем говорится, что вещь, которую вы пытаетесь использовать, вовсе не является «структурой». (Как объясняются ниже, ваш код обрабатывается как '* (a-> a)', 'a-> a' - это то же самое, что и' (* a) .a', а тип '* a' это 'A *', т. е. компилятор думает, что вы пытаетесь получить доступ к элементам указателя, что не имеет смысла.) – melpomene

ответ

4

Вы должны добавить круглые скобки:

void init(A **a) 
{ 
    *a = malloc(sizeof(A)); // bad you don't verify the return of malloc 
    (*a)->a = 3; 
    (*a)->b = 2; 
    (*a)->c = 1; 
} 

Но это хорошая практика, чтобы сделать это:

void init(A **a) 
{ 
    A *ret = malloc(sizeof *ret); // we want the size that is referenced by ret 
    if (ret != NULL) { // you should check the return of malloc 
     ret->a = 3; 
     ret->b = 2; 
     ret->c = 1; 
    } 
    *a = ret; 
} 
3

Вы должны написать (*a)->a = 3; по причинам приоритета.

+0

Wow на самом деле не думал, что это вопрос синтаксиса. Спасибо! – Primemaster

3

Ваша проблема - приоритет оператора. Оператор -> имеет более высокий приоритет, чем оператор * (разыменованный), поэтому *a->a считывается так, как будто это *(a->a). Изменить *a->a в (*a)->a:

#include <stdio.h> 
#include <stdlib.h> 

typedef struct 
{ 
    int a; 
    int b; 
    int c; 
}A; 

A *test; 

void init(A** a) 
{ 
    *a = malloc(sizeof(A)); 
    (*a)->a = 3; 
    (*a)->b = 2; 
    (*a)->c = 1; 
} 
int main() 
{ 
    init(&test); 
    printf("%d\n", test->a); 
    return 0; 
} 
3

Несмотря на то, что это не является прямым ответом на ваш вопрос, поскольку мы находимся в непосредственной близости от инициализации, я хотел бы указать, что C11 дает вам более сильный синтаксис для инициализации структур:

void init(A **a) 
{ 
    A *ret = malloc(sizeof *ret); // we want the size that is referenced by ret 
    if (ret != NULL) { // you should check the return of malloc 
     *ret = (A) {3, 2, 1}; 
     // or 
     *ret = (A) { .a = 3, .b = 2, .c = 1 }; 
    } 
    *a = ret; 
} 

Другим преимуществом является то, что любые неинициализированные элементы обнуляются.

+0

Очень интересный пользовательский документ [здесь] (http://en.cppreference.com/w/c/language/compound_literal). Но я хочу знать, создает ли временную переменную или влияет только на структуру. – Stargateur

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