Вопрос

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

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)bytelocations..неудивительно, что у меня были нарушения прав доступа, я пытался прочитать то, что не должен был читать..:)

Это было полезно?

Решение

«++» — это просто другое имя для X = X + 1;

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

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

Другие советы

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

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

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

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

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

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

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


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

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

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

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

pChar+2; // increment the address pointed to by pChar by 2 bytes
pInt+2; // increment the address pointed to by pInt by 8 bytes

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

memcpy(pChar+5,pInt+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 байта на каждом шаге (хотя для массива целых чисел это нормально).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top