как работает указатель адресации в с ++ - PullRequest
4 голосов
/ 02 апреля 2012

Я не совсем понимаю, что указатель указывает на адрес переменной image

, он указывает на последние два байта, как это работает

#include <iostream>
using namespace std;

int main()
{
    int i = 1;
    short *j  = (short*)&i;
    cout << *j << endl;
}

.

Ответы [ 5 ]

11 голосов
/ 02 апреля 2012

Указатель обычно содержит адрес начала упомянутого элемента.

Судя по всему, вы, очевидно, используете систему с прямым порядком байтов [править: что неудивительно - например, текущие (Intel) Mac и все Windows-машины имеют младший порядок байтов], что означает младший значащий байт вашего 4-байтового int приходит первым в памяти вместо последнего:

0000001 00000000 00000000 00000000

Когда вы используете указатель на short для просмотра первых двух байтов, вы получаете:

0000001 00000000

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

Как следует из названия "little-endian", существуют также системы с прямым порядком байтов, в которых данные будут размещены, как показано выше. На такой машине вы, вероятно, получите ожидаемые результаты. Просто чтобы быть завершенным, есть также несколько систем, которые используют довольно странные механизмы, которые могут запускать что-то вроде byte1 byte0 byte3 byte2.

3 голосов
/ 02 апреля 2012

Это не указывает на байты;он указывает на сущность типа int.То, как int представляется в памяти, зависит от реализации.И если i является int, то *((short*)&i) является неопределенным поведением;Вы можете получить что угодно.На практике на общих платформах вы можете получить доступ к таким вещам;то, что вы по-прежнему получаете, зависит от платформы, и такие манипуляции полезны только для очень низкоуровневых, специфичных для платформы операций.(На Intel вы получите результаты, опубликованные другими. Это зависит от других платформ и других значений.)

3 голосов
/ 02 апреля 2012

Это зависит от порядкового номера вашей системы (x86 обычно имеет младший порядковый номер).

В старшем порядке, значение i будет храниться с самым старшим байтом первым:

00000000 00000000 00000000 00000001

В младшем порядке, значение i будет храниться с наименьшим значащим байтом первым:

00000001 00000000 00000000 00000000

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

00000001 00000000

В младшем порядке это короткое значение 1, которое является результатом, который вы получаете. Если вы выполняете точно такой же код в системе с прямым порядком байтов, вы получите значение 0.

3 голосов
/ 02 апреля 2012

Это связано с порядком байтов.Ваша архитектура хранит int 1 как:

00000001 00000000 00000000 00000000
^^^^^^^^
  this is the address that is stored in the pointer.
|------- -------- -------- --------| int (4 bytes)
|------- -------|                    short (2 bytes)

, который, усеченный до short из 2 байтов, все еще равен 1.

Btw.попробуйте распечатать все байты самостоятельно:

unsigned char* p = (unsigned char*)&i;
for (unsigned j = 0; j < sizeof(int); j++) {
  std::cout << p[j] << " ";
}
std::cout << std::endl;

Он должен напечатать 1 0 0 0, а не 0 0 0 1, как предлагается в вашем вопросе.

3 голосов
/ 02 апреля 2012

Это зависит от архитектуры.И конкретная реализация должна быть совершенно неактуальной (если вы не делаете что-то не так).

...