Почему указатель арифметики должен быть приведен? - PullRequest
0 голосов
/ 03 июля 2018

Если бы я хотел перебрать строку, в данном случае 'test', я мог бы использовать арифметику указателей, например, чтобы перейти к следующему символу:

char *c = "test";
*c++;
putchar(*c);

Это напечатало бы вторую букву 'e'.

Но, если я хочу перейти к третьему персонажу, почему я не могу сказать:

char *c = "test";
c = *c + 2;        //*c = *c + 2; also doesn't work
putchar(*c);       //Exception thrown: write access violation.

Насколько мне известно, единственный способ добраться до третьего символа с использованием арифметики с указателями - это привести его так:

char *c = "test";
c = (char *) c + 2;
putchar(*c);

Может кто-нибудь объяснить мне, почему это так?

Ответы [ 4 ]

0 голосов
/ 03 июля 2018

Давайте разберемся в следующем коде:

char * c = "test";
c = *c + 2; //*c = *c + 2; also doesn't work
putchar(*c);//Exception thrown: write access violation.

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

Второе утверждение говорит, что примите значение по адресу в местоположении, указанном c (ASCII 'e' равен 0x65), добавьте 2 к нему и сохраните его как новый адрес. Переменная c теперь содержит 0x67.

В третьем утверждении указывается значение печати в виде адреса, хранящегося в c (который теперь равен 0x67) Поскольку у нас нет доступа к этой ячейке памяти, возникает исключение.

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

char * c = "test";
c = c + 2; //Moves the pointer by 2 bytes
putchar(*c); //Print the character at that memory location
0 голосов
/ 03 июля 2018

В вашем первом примере c++; просто добавляет один к c, без разыменования, так почему вы пытаетесь разыменовать при добавлении 2? Просто добавьте 2 к значению указателя:

char * c = "test";
c = c + 2; //*c = *c + 2; also doesn't work
putchar(*c);//Exception thrown: write access violation.
0 голосов
/ 03 июля 2018

Ваш первый фрагмент кода был

char * c = "test";
*c++;
putchar(*c);

и, как вы заметили, он печатает e. Но важно отметить, что во второй строке * совершенно лишний. Вы увеличили c, и , извлекли указатель на символ - и затем выбросили указатель на символ.

Это работало бы точно так же - и было бы более понятным, без запутанных, лишних операторов - если бы вы вместо этого сказали

char * c = "test";
c++;
putchar(*c);

Затем вы задались вопросом, почему вы не можете увеличить указатель на 2. Но, конечно, вы можете увеличить указатель на два - вы можете либо сказать

char * c = "test";
c++;
c++;
putchar(*c);

или

char * c = "test";
c += 2;
putchar(*c);

или

char * c = "test";
c = c + 2;
putchar(*c);

Но вы написали

c = *c + 2;

Это не сработало, и неудивительно - опять же, у вас есть ненужное *, и здесь это не так безобидно. Здесь вы без необходимости извлекаете символ, на который указывает c, но вместо того, чтобы выбросить его, вы добавляете к нему 2, , а затем пытаетесь присвоить символ исходной переменной указателя . Ваш компилятор, вероятно, жаловался на это - назначение символа указателю не имеет смысла. Это как если бы вы сказали

c = 'x';

Похоже, вы не уверены, что означает * в C. Это , а не просто маркер, который говорит, что «эта переменная является указателем». Это оператор, который активно выбирает значение, на которое указывает указатель.

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

Возвращаясь к исходному примеру, когда вы сказали

char * c = "test";

значение указателя c - это «указатель на первый символ строки», а значение, на которое указывает указатель, - «символ t».

Если вы скажете

c++

Вы увеличиваете значение указателя. Теперь он указывает на второй символ строки, а указанным значением является символ e.

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

0 голосов
/ 03 июля 2018

c здесь указатель, который содержит адрес ячейки памяти.

*c называется разыменованием указателя, который даст значение, сохраненное в ячейке памяти, на которое указывает c.

So

c = *c + 2

будет

c = (value stored at c) + 2;

, который не даст место в памяти, как

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