Указатель типов данных в C - PullRequest
2 голосов
/ 11 февраля 2012

Если у меня есть указатель вроде:

int* ptr;

и я делаю:

printf("%#x\n%#x\n%#x\n", ptr, ptr+1, ptr+2);

Я получаю вывод как:

some address
some address + 4bytes
some address + 8bytes

Теперь, если я сделаю указатель short int* ptr

Я печатаю так же, как указано выше, и получаю вывод:

some address
some address + 2bytes
some address + 4bytes

Почему это? Разве адреса не подписаны целыми числами? Если это так, то тип данных, на который указывает указатель, не должен иметь значения. Указатель всегда будет хранить адрес без знака int, следовательно, он будет занимать 4 байта. Почему короткий указатель int занимает 2 байта, а указатель int занимает 4 байта? В конце концов, оба указателя хранят только адреса, не так ли?

Ответы [ 5 ]

3 голосов
/ 11 февраля 2012

Арифметика указателя (т.е. ptr+n) выполняется в единицах того, на что указывает вещь.

Помните, что ptr+n эквивалентно &ptr[n], поэтому оно также эквивалентно:

(T *)((char *)ptr + n*sizeof(T))

, где T - это любой тип, на который вы указываете.


Кстати, вы должны использовать %p для отображения указателей, а не %#x.

1 голос
/ 11 февраля 2012

Если вы сделаете

int* ptr;
printf("%#x\n%#x\n%#x\n", ptr, ptr+1, ptr+2);

Компилятор говорит: «Эй, ptr указывает на некоторое значение int, и программист хочет, чтобы int s со смещением 1 или 2 дюйма.Итак, я получаю sizeof(int) (что на многих архитектурах, включая вашу, 4 байта) и добавляю его к значению ptr ".Таким образом, выходные данные будут смещены на 4 байта.

Расположение в памяти:

ptr --+
      |
      v
      +---------+---------+---------+
      |   int   |   int   |    int  |
      +---------+---------+---------+
        4 bytes   4 bytes   4 bytes

При выполнении

unsigned int* ptr;
printf("%#x\n%#x\n%#x\n", ptr, ptr+1, ptr+2);

Компилятор говорит: «Эй, ptr указывает на некоторый unsigned int, и программистхочет unsigned int s со смещением 1 или 2 дюйма. Итак, я получаю sizeof(unsigned int) (что на многих архитектурах, включая вашу, 2 байта) и добавляю его к значению ptr ".Таким образом, выходные данные будут смещены на 2 байта.

Расположение в памяти:

ptr --+
      |
      v
      +---------+---------+---------+
      |unsigned | unsigned|unsigned |
      +---------+---------+---------+
        2 bytes   2 bytes   2 bytes
0 голосов
/ 11 марта 2017

да указатели являются целыми числами без знака, теперь с учетом определения int *ptr

ptr не представляет адрес указателя, он представляет адрес переменной, на которую указывает указатель, а размер будет зависеть от типа переменной, на которую он указывает. если бы вы сделали что-то подобное для указателя, указывающего на любой тип, printf("%x %x %x",&ptr,&ptr+1,&ptr+2), тогда разница между адресами будет такой же

0 голосов
/ 11 февраля 2012

Вы правы, указатели хранят адреса.Однако когда вы говорите int* ptr, он выделяет 4 байта в памяти , так что любое новое распределение не коснется этой области.Аналогично short занимает 2 байта, следовательно, он выделяет 2 байта в памяти.

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

Вы можете прочитать это: http://www.taranets.net/cgi/ts/1.37/ts.ws.pl?w=329;b=279

0 голосов
/ 11 февраля 2012

Арифметика указателей отличается от обычной целочисленной арифметики. Компилятор имеет в виду длину типа переменной, на которую указывает указатель, и добавляет к адресу эту длину, а не просто число 1, 2 и т. Д.

...