C: оператор -> и *

На следующем примере:

typedef struct {
    const char *description;
    float value;
} swag;

typedef struct {
    swag *swag;
    const char *sequence;
} combination;

typedef struct {
    combination numbers;
    const char *make;
} safe;

int main()
{
    swag gold = {"GOLD!", 1000000.0};
    combination numbers = {&gold, "6502"};
    safe s = {numbers, "RAMACON250"};

    //Correct handling
    printf("Result: %s \n", s.numbers.swag->description);

    //Faulty handling
    // printf("Result: %s \n", s.numbers.(*swag).description);

    return 0;
}

следующая строка правильна, чтобы получить "GOLD!"

printf("Result: %s \n", s.numbers.swag->description);

но почему следующее неверно как (*x).y такой же как x->y

printf("Result: %s \n", s.numbers.(*swag).description);

Я получаю следующую ошибку во время компиляции:

C: \ main.c | 26 | ошибка: ожидаемый идентификатор перед '(' токен |)

4 ответа

Решение

Просто используйте

printf("Result: %s \n", ( *s.numbers.swag).description);

Согласно грамматике C постфиксное выражение . определяется следующим образом

postfix-expression . identifier

Так что вы можете написать, например,

( identifier1 ).identifier2

но ты не можешь писать

identifier1.( identifier2 )

Возвращаясь к своей программе, вы могли бы даже написать

printf("Result: %s \n", ( *( ( ( s ).numbers ).swag ) ).description);

почему следующее неверно, так как (*x).y совпадает с x->y

printf("Result: %s \n", s.numbers.(*swag).description);

Вы правы насчет (*x).y быть таким же, как x->y

Но это не то, что вы делаете в коде:

s.numbers.(*swag).description

Посмотрите на это так:

when comparing s.numbers.swag->description to x->y

x is s.numbers.swag
y is description

so by simple substitution

x->y equivalent to (*x).y becomes (*s.numbers.swag).description

Просто замените *swag на swag[0].

printf("Result: %s \n", s.numbers.swag[0].description);

Помните, *swag и swag[0], это одно и то же.

. и -> имеют одинаковый приоритет операторов и их ассоциативность слева направо. Поэтому

s.numbers.swag->description

работает отлично. И, интуитивно, вы можете следить за тем, что решено, слева направо. Вы получаете доступ s затем numbers затем swag, к которому вы обращаетесь, чтобы получить доступ description,

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

s.numbers.(*swag).description

должно быть эквивалентно вышеуказанному. Это не относится к делу.

Это потому что (унарный) * оператор имеет более низкий приоритет, чем . а также ->, и его ассоциативность справа налево, и установка круглых скобок не исправляет это (Вы хотите получить доступ к swag указатель а не swag членом).

Что это эффективно делает: Доступ s затем numbers тогда разыменованный swag (чисел) и попробуйте получить доступ description, Но numbers имеет только указатель на swag и не swag член.

Эквивалентные выражения уже упоминались в другом ответе, который я повторяю здесь для полноты:

(*s.numbers.swag).description

Доступ s затем numbers затем swag и связь с описанием доступа. Помните . имеет более высокий приоритет, чем * и скобки разрешаются до . чтобы получить доступ к описанию из-за связи слева направо.

s.numbers.swag[0].description

Доступ s затем numbers затем swag и разыменование для доступа к описанию. [] оператор имеет такой же приоритет и ассоциативность, как ., Таким образом, вы можете прочитать это выражение слева направо.

Другие вопросы по тегам