Страницы

Поиск по вопросам

понедельник, 8 октября 2018 г.

В чём разница между одиночными и двойными указателями?

Здравствуйте! Прошу объяснить разницу между двойными и одиночными указателями на примере двух приведённых ниже программ: они одинаковые, только первая использует одиночные указатели, а вторая - двойные. Меня интересует, почему в первой программе строка ++(currentChar) не приводит к движению по строке чисел, а во второй соответствующая строка ++(*currentChar) приводит, другими словами, почему "область действия одиночного указателя ограничивается функцией, в пределах которой он задан" (кавычки, потому что знаю, что это может быть не точно) ? Просьба не ругать за отсутствие элементарных познаний в языке C - я постепенно спускаюсь к нему с более высокого уровня (Objective-C), и до сих пор не выдавалось время изучить C системно. Спасибо. После ответов и обсуждения выяснилось, что на самом деле ключевая разница (ох, незнание основ!!) состоит в том, как передаются аргументы: в первом случае это просто currentChar, а во втором это ¤tChar. См. ответы и обсуждение. Программа №1 void func1(const char *currentChar) { printf("char is %c
", *currentChar);
++(currentChar); }
int main(int argc, const char * argv[]) { char *JSONCString2 = "123456789";
const char *currentChar = JSONCString2;
while (currentChar != NULL && *currentChar != '\0') { func1(currentChar); }
return 0; } Её вывод: бесконечное повторяющееся char is 1 Программа №2 void func1(const char **currentChar) { printf("char is %c
", **currentChar);
++(*currentChar); }
int main(int argc, const char * argv[]) { char *JSONCString2 = "123456789";
const char *currentChar = JSONCString2;
while (currentChar != NULL && *currentChar != '\0') { func1(¤tChar); }
return 0; }
char is 1 char is 2 char is 3 char is 4 char is 5 char is 6 char is 7 char is 8 char is 9 Program ended with exit code: 0


Ответ

Указатель - это обыкновенная переменная, которая хранит не данные, а некий адрес, который ссылается на ячейку данных. "Размер" этой ячейки зависит от типа указателя (не сам размер, а размер ячейки, которую он адресует, это важно для адресной арифметики, см. далее). Логично, что мы можем делать указатель на указатель с условно бесконечной глубиной вложенности. Можно получать адреса, относительно указателя "сдвигая" его вправо (прибавляя целое число) и влево (отнимая целое число) на размер типа указателя. UPD В первый раз мы передаем указатель по значению (каждый раз копируем значение), второй раз - по ссылке (работаем с ним непосредственно). Поэтому инкремент в первом случае не работает мы будем "топтаться на месте". из аргумента). Ну и при обращении к строке (в printf) в первый раз мы один раз извлекаем указатель (разыменовываем), а во второй - дважды, получая сначала адрес указателя на данные, а затем - и сами данные.

Комментариев нет:

Отправить комментарий