Приведение int указателя на длинный указатель в C / C ++ - PullRequest
0 голосов
/ 22 февраля 2019

Предположим, у меня есть следующий код C

#include <stdio.h>

int main(){ 
 int a = 5;
 int b = 6;
 int c = 7;
 void *d = &a;
 long *ld = (long *)d;
 printf("%ld\n", *ld);
 return 0;
}

Выполняя sizeof с использованием gdb, я вижу, что int - это 4 байта, а long - это 8 байтов на моемlittle endian, x64 machine.

Вывод вышеприведенного printf равен 5.

Мой вопрос: как значение 5, несмотря на тот факт, что мой указатель ldтеперь 64 бита и указывает на первый байт a (32-битный переменный).Как это не переполняется, когда я разыменую это?Как это не включает байты в b и c?Откуда он знает, что после 32-х битного счета перестать считать, хотя это 64-битный указатель?

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Поведение должно зависеть от компилятора и флага.Например, ваш точный код в моем тесте:

% gcc x.c -W -Wall -O2
% ./a.out 
5
% gcc x.c -W -Wall -O0
% ./a.out 
-90829968375803

Память, в которой хранятся a, b, c, может быть оптимизирована или переставлена, перестроена в стеке, зависит от компилятора и флагов.

0 голосов
/ 22 февраля 2019

Это переполнение, и, как отмечено в первом комментарии, это неопределенное поведение.

Могут быть разные причины не достичь b или c.Во-первых, поскольку они не используются, они могут быть оптимизированы.Если они были использованы, то, пока вы не получили их адрес, они могут находиться в реестре.Если они находятся в стеке, порядок переменных в стеке может быть другим, и возможно также добавление заполнения.

Объединение их в единую структуру может затруднить оптимизацию и упорядочение.Глобальная переменная этого типа структуры работает с большей вероятностью.Но в любом случае ничего не гарантировано, так как это все еще неопределенное поведение.

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