В чем смысл типов указателей в C ++? - PullRequest
3 голосов
/ 19 декабря 2008

Допустим, у меня есть несколько указателей под названием:

char * pChar;
int * pInt;

Я знаю, что они оба просто хранят адреса памяти, которые указывают на какое-то другое местоположение, и что типы объявляют, на какой объем памяти указывает конкретный указатель. Так, например, char может быть размером байта в системе, а int может быть 4 байта. Так что, когда я делаю:

pChar++; // I am actually incrementing the address pointed to by pChar by 1 byte;
pInt++; // I am actually incrementing the address pointed to by pInt by 4 bytes;

Но что, если я сделаю это:

pChar+2; // increment the address pointed to by pChar by 2 bytes?
pInt+2; // increment the address pointed to by pInt by 2 bytes? what happens to the other two bytes?

Спасибо .. Буду признателен за разъяснения здесь .. Является ли тип указателя просто для операции ++?

РЕДАКТИРОВАТЬ: Таким образом, avp ответил на мой вопрос правильно, но у меня есть дополнительный вопрос, что происходит, когда я делаю:

memcpy(pChar,pInt,2);

Будет ли копировать 2 байта? или 4 байта? Будет ли у меня нарушение прав доступа?

РЕДАКТИРОВАТЬ: Ответ, согласно Райану Фоксу, составляет 2 байта, потому что они приведены к типу (void *). Спасибо! ЗАКРЫТО!

РЕДАКТИРОВАТЬ: Просто для того, чтобы будущие поисковики могли найти это .. Другая часть информации, которую я обнаружил ..

memcpy(pChar+5,pInt+5,2);

не копирует 2 байта блока памяти, на который указывают pInt + 5bytelocations, в pChar + 5bytelocations ... что происходит, когда 2 байта копируются в pChar + 5bytelocations из pInt (4 * 5) байтовых расположений ... неудивительно нарушения доступа, я пытался зачитать где-то, что я не должен был читать ..:)

Ответы [ 5 ]

7 голосов
/ 19 декабря 2008

"++" - это просто другое имя для X = X + 1;

Для указателей не имеет значения, увеличиваете ли вы на 1 или на N. В любом случае, sizeof (тип) * N используется. В случае 1 это будет просто sizeof (тип).

Итак, когда вы увеличиваете на 2 (ваш второй случай):
для символа - 2 * sizeof (char) = 2 * 1 = 2 байта,
для int будет 2 * sizeof (int) = 2 * 4 = 8 байт.

5 голосов
/ 19 декабря 2008

Ааа, теперь я понимаю. Вы должны были спросить - «Какой смысл указателей, имеющих типы?»

На самом деле есть два момента:

  • арифметика указателей;
  • Разыменование (возврат значения, сохраненного в адресе, на который указывает указатель).

И то, и другое невозможно без знания типа указателя.

Добавлено: Прочитать документацию к memcpy. Последний аргумент - это число байтов, потому что memcpy понятия не имеет, какой тип указателя. Оба аргумента для этого являются пустыми указателями.

Добавлено 2: Нарушение прав доступа - это зависит. Если вы не выходите за пределы памяти, выделенной для этих указателей, нарушения доступа не будет. Операция копирования будет копировать все побайтно, и вы получите свои результаты точно так же, как вы ожидаете их (хотя это может не иметь большого смысла).

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


Есть три основных преимущества указателей:

  1. Вы можете передавать аргументы функции "по ссылке". Раньше это было больше проблемой в C, который не имел реальных ссылок, таких как C ++, но он все еще очень полезен во многих случаях, например, когда вам приходится работать с внешними библиотеками. Также обратите внимание, что передача по ссылке полезна не только тогда, когда вы хотите, чтобы функция изменила передаваемую вами переменную. Это также очень хорошо для передачи больших структур данных в качестве параметров.
  2. Для построения всех видов изящных динамических структур данных, таких как деревья, связанные списки и т. Д. Это было бы невозможно без указателей.
  3. Для возможности перераспределения массивов на большие / меньшие по мере необходимости.

P.S. Я понимаю, что вопрос был о том, почему указатели хороши, используя арифметику только в качестве примера, верно?

3 голосов
/ 19 декабря 2008

Арифметика указателей не работает именно так. Ваш первый пример правильный, второй не так уж и много.

pChar+2; // increment the address pointed to by pChar by 2 bytes
pInt+2; // increment the address pointed to by pInt by 8 bytes
1 голос
/ 19 декабря 2008

Для этой части:

тетср (Pchar + 5, пинта + 5,2);

Сначала оценивается "+", а затем тип.

Итак, в байтах:

pChar + 5 здесь "5" - это 5 байтов,
pInt + 5 здесь "5" - это 5 дюймов, поэтому 5 * 4 = 20 байтов.
Затем все преобразуется в void * и копируются два байта.

Если вместо «5» вы используете счетчик, как здесь:

for (int i = 0; i<100; i++)
    memcpy(pChar+i, pInt+i, 2);

Тогда для pChar вы будете перезаписывать один скопированный байт (второй) следующей командой копирования. И для pInt вы будете прыгать 4 байта за каждый шаг (хотя это нормально для массива целых чисел).

0 голосов
/ 19 декабря 2008

Я бы сказал, что точка типов указателей в C ++ предназначена для учета смещений vtable.

...