C Структура в качестве аргумента - PullRequest
0 голосов
/ 24 марта 2010

Мне интересно, в чем разница между sample1 и sample2. Почему иногда мне приходится передавать структуру в качестве аргумента, а иногда я могу сделать это, не передавая ее в функцию? и как было бы, если для работы функции samplex требуется несколько структур? Вы бы передали несколько структур в качестве аргумента?

struct x
{
    int  a;
    int  b;
    char *c;
};

void sample1(struct x **z;){
    printf(" first member is %d \n", z[0]->a);
}

void sample2(){
    struct x **z;
    printf(" first member is %d \n", z[0]->a); // seg fault
}

int main(void)
{
    struct x **z;

    sample1(z);
    sample2();

    return 0;
}

Ответы [ 4 ]

1 голос
/ 24 марта 2010

Прежде всего, ваш тип аргумента не struct, а указатель на указатель на struct (или массив указателей на struct - они семантически эквивалентны с точки зрения вызываемого, за исключением того, что адрес массива может не подлежит изменению).

Во втором случае вы используете локальную переменную, которая полностью независима от переменной с тем же именем в main. Поскольку он не инициализирован, вы получаете ошибку сегмента при попытке доступа к одному из его членов. (Элемент в main также не инициализируется, но доступ к нему просто кажется случайным в sample1).

Вам следует инициализировать свои переменные перед их использованием, в противном случае вы вводите территорию неопределенное поведение . Э.Г.

void sample1(struct x **z){
    printf(" first member is %d \n", z[0]->a);
}

void sample2(){
    struct x z[1];
    z[0].a = 1;
    ...
    printf(" first member is %d \n", z[0].a);
}

int main(void)
{
    struct x z[1];

    z[0].a = 1;
    ...
    sample1(z);
    sample2();

    return 0;
}
0 голосов
/ 24 марта 2010

Ваша декларация

struct x **z;

просто создает указатель на указатель на структуру типа x. Вы на самом деле не инициализируете указатели, т.е.

Попробуйте что-то вроде

struct x z;
struct x *pZ = &z;

sample1(&pZ);

(Я не совсем уверен, чего вы на самом деле пытаетесь достичь!)

0 голосов
/ 24 марта 2010

C и C-подобные языки имеют понятие «область действия». Видите все эти фигурные скобки ({ и })? Это "блоки". По сути, они заключают весь код между ними в пакеты, которые не зависят от каких-либо других блоков на том же уровне. Любая переменная, которую вы создаете в этом блоке, доступна только внутри этого блока - вы не можете ссылаться на нее где-либо еще.

Вы можете создать вложенный блок. Например:

int f() {
    int x;
    scanf("%d", &x);
    if (x == 3) {
        return 7;
    }
    else {
        return x;
    }
}

Как видите, блок else вложен в блок функции, и поэтому может обращаться к переменным функции.

Когда вы объявляете struct x **z в main и sample2, вы фактически создаете две переменные, каждая из которых называется z. Они полностью независимы - они совсем не одна и та же переменная. Они не связаны. Единственное, что у них общего, это их имя и тип - фактическое значение другое. Единственный способ использовать одну и ту же переменную в обоих случаях - передать, как в sample1.

Конечно, в данный момент ваш указатель z является мусором - вы ничего не выделили. Я бы порекомендовал вам что-то там хранить, прежде чем пытаться разыменовать это.

0 голосов
/ 24 марта 2010

Оба недействительны и имеют доступ к плохой памяти. Результаты не определены, поэтому оба результата верны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...