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

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

/****************************************************************************
 *                                                                          *
 * 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.

Білий Лунь

2

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

struct entry *list_pointer = &n1;

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

struct entry *list_pointer = 

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

= &n1;

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

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

I belong to the Dead Generation.
Подякували: Ярослав1

3 Востаннє редагувалося Ярослав (30.01.2013 17:20:03)

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; // не правильно

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

Білий Лунь

4

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;
I belong to the Dead Generation.
Подякували: Ярослав1

5

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

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

I belong to the Dead Generation.

6

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

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

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

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

I belong to the Dead Generation.