#### Тема: Порядок виконання операторів, Сі

Маю код із книги Стефана Кочана:

``````/****************************************************************************
*                                                                          *
* File    : main.c                                                         *
*                                                                          *
* Purpose : Console mode (command line) program.                           *
*                                                                          *
* History : Date      Reason                                               *
*           00/00/00  Created                                              *
*                                                                          *
****************************************************************************/

#include <stdio.h>

/****************************************************************************
*                                                                          *
* Function: main                                                           *
*                                                                          *
* Purpose : Main entry point.                                              *
*                                                                          *
* History : Date      Reason                                               *
*           00/00/00  Created                                              *
*                                                                          *
****************************************************************************/

int main(int argc, char *argv[])
{
struct entry{
int value;
struct entry *next;
};
struct entry n1, n2, n3;
struct entry *list_pointer = &n1;

n1.value = 100;
n1.next = &n2;
n2.value = 200;
n2.next = &n3;
n3.value = 300;
n3.next = (struct entry *) 0;

while(list_pointer != (struct entry *) 0){
printf("%i\n", list_pointer->value);
list_pointer = list_pointer->next;
}
return 0;
}``````

Мене цікавить, в якому порядку виконуються оператори тут:
struct entry *list_pointer = &n1;
Оператор розйменування має пріорітет 3, побітове І (&) 10, пряме присвоєння 16.

#### Re: Порядок виконання операторів, Сі

``struct entry *list_pointer = &n1;``

Читаємо зліва направо:

``struct entry *list_pointer = ``

1. Створився покажчик на entry. Відповідно, наступний за ним оператор присвоєння має справа мати об'єкт подібного типу.
Далі йде аналіз правої частини:

``= &n1;``

2. Оскільки необхідно отримати об'єкт типу entry*, амперсанд розпізнається як оператор взяття адреси.
3. Присвоєння йде останнім за пріоритетом.

Чи ви щось інше мали на увазі?

#### Re: Порядок виконання операторів, Сі

Коли ми надаємо адресу покажчику - ми пишемо так:

``````int *ptr; // покажчик на int
int a = 20;
ptr = &a;``````

Без оператору розйменування.
А коли вказуємо адресу одразу під час ініціалізації або оголошення, виправте мене, то задаємо разом із цим оператором:

``````int a = 20;
int *ptr = &a;``````

Якщо ми задамо тому, на що вказує покажчик, який іще не визначений, адресу a, то програма не скомпілюється.
Тобто

``````int *ptr = &a; // правильно

int a = 20;
int *ptr;
*ptr = &a; // не правильно``````

Я хочу зрозуміти чому.
Перше що мені прийшло в голову - це пріоритет операторів.

#### Re: Порядок виконання операторів, Сі

keithfay написав:

Якщо ми задамо тому, на що вказує покажчик, який іще не визначений, адресу a, то програма не скомпілюється.
Тобто

``````int *ptr = &a; // правильно

int a = 20;
int *ptr;
*ptr = &a; // не правильно``````

Я хочу зрозуміти чому.
Перше що мені прийшло в голову - це пріоритет операторів.

Покажчик - це змінна, що містить адресу. Коли ви створюєте покажчик, ви кажете компілятору

``int *ptr;``

де зірочка позначає створення саме покажчика на int, а не просто int-змінної. І тільки у цей момент зірочка означає "зберігати адресу змінної типу int". Коли ж ви надалі використовуєте зірочку щодо цього покажчика, вона означає доступ до значення змінної, на яку вказує покажчик. Тому, коли ви спробували вчинити

``*ptr = &a;``

компілятор справедливо відповів, що змінна типу int не конче підходить для зберігання значення типу int*.

Виходячи з цього:
- якщо вам треба перенаправити покажчик:

``````int *p = 0;
int a;
p = &a;``````

- якщо потрібно змінити значення змінної під покажчиком:

``````int a = 1;
int *p = &a;
*p = 2; /* a = 2 */``````

З.І: Програмісти Мілкософта, вочевидь, мали схожу проблему, оскільки одним з їхніх "коників" є використання typedef, на зразок:

``````typedef int* Pint;
int a;
Pint myPointer = &a;``````

#### Re: Порядок виконання операторів, Сі

Ще маленьке доповнення до теми - така собі історична довідка від Рітчі.

#### Re: Порядок виконання операторів, Сі

Якщо буде бажання, спробуйте для практики розкласти по поличках таке:

``void (*signal(int signal, void (*func)(int))) (int);``

Прототип функції з <csignal>.