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
и разыменование для доступа к описанию. []
оператор имеет такой же приоритет и ассоциативность, как .
, Таким образом, вы можете прочитать это выражение слева направо.