Объяснение «эффективного типа»? - PullRequest
6 голосов
/ 20 июня 2019

Я читаю спецификацию C, в которой указано 6.5 выражений

Эффективным типом объекта для доступа к его сохраненному значению является объявленный тип объекта, если таковой имеется. Если значение сохраняется в объекте, у которого нет объявленного типа, через lvalue, имеющий тип, который не является символьным типом, то тип lvalue становится эффективным типом объекта для этого доступа и для последующих доступов, которые не изменяют сохраненное значение.

Может кто-нибудь объяснить, что это значит? У меня смутное ощущение, что это связано с указателями и malloc(), но это насколько я могу получить без помощи адвоката ...

Обновление на основе ответа: Могу ли я безопасно сделать это?

struct point {
    int x;
    int y;
};

int main() {
    int *x = malloc(1000);
    *x = 10;
    printf("%d\n", *x);

    struct point *p = x;
    p->x = 5;
    p->y = 10;
    printf("%d %d\n", p->x, p->y);
}

Я получаю предупреждение, но оно работает в моем случае. Гарантируется ли работа?

1 Ответ

6 голосов
/ 20 июня 2019

Когда вы объявляете переменную данного типа, она ссылается на базовый объект этого типа, поэтому эффективным типом объекта является тип связанной переменной.

Когда все становится немного неясным, когда malloc вступает в игру. Память, возвращаемая из malloc, не имеет действующего типа. Например:

int *x = malloc(sizeof(int));

Предполагая, что int имеет размер 4 байта, x теперь указывает на 4 байта памяти без действующего типа. Эта память получает эффективный тип при назначении:

*x = 123;

Теперь эти байты имеют эффективный тип int.

В нашем примере вы выделяете 1000 байтов, и изначально эти байты не имеют действующего типа.

*x = 10;

Это делает первые sizeof(int) байтов объектом типа int.

struct point *p = x;

Этот должен иметь приведение, но в конце все нормально, потому что первый член struct point имеет тип int, а указатель на структуру указывает на его первый член.

p->x = 5;

Это безопасно, потому что &p->x указывает на объект типа int, который соответствует типу lvalue p->x.

p->y = 10;

Это также безопасно, поскольку байты, на которые указывает &p->y, еще не имеют действующего типа, и присваивание приводит к тому, что следующие sizeof(int) байты будут объектами типа int.

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