Я только начинаю с указателей, и я немного запутался. Я знаю, что &
означает адрес переменной и который *
может быть использован перед переменной указателя, чтобы получить значение объекта, на который указывает указатель. Но все работает иначе, когда вы работаете с массивами, строками или когда вы вызываете функции с копией указателя на переменную. Трудно увидеть паттерн логики внутри всего этого.
Когда я должен использовать &
и *
?
RTFM
бесполезно, и, откровенно говоря, очень грубо. Если у вас нет времени, чтобы ответить, относитесь с уважением к тем, кто находит время, чтобы ответить на эти вопросы. Хотелось бы @ это «анонить», но, очевидно, у него / нее нет времени внести какой-либо значимый вклад.Ответы:
У вас есть указатели и значения:
Вы превращаете указатель в значение с помощью
*
:Вы превращаете значение в указатель с помощью
&
:Изменить: В случае массивов, они очень похожи на указатели. Если вы думаете о них как о указателях, вы будете использовать
*
для получения значений внутри них, как описано выше, но есть и другой, более распространенный способ использования[]
оператора:Чтобы получить второй элемент:
Так что
[]
оператор индексирования - это особая форма*
оператора, и он работает так:источник
int aX[] = {3, 4}; int *bX = &aX;
int *bX = &aX;
не работает, потому чтоaX
уже возвращает адресaX[0]
(то есть&aX[0]
), поэтому&aX
получил бы адрес, который не имеет смысла. Это верно?int aX[] = {3,4};
,int **bX = &aX;
является ошибкой.&aX
имеет тип «указатель на массив [2] изint
», а не «указатель на указатель наint
». В частности, имя массива не рассматривается как указатель на его первый элемент для унарного&
. Вы можете сделать:int (*bX)[2] = &aX;
Существует закономерность при работе с массивами и функциями; сначала это немного сложно увидеть.
При работе с массивами полезно помнить следующее: когда выражение массива появляется в большинстве контекстов, тип выражения неявно преобразуется из «N-элементного массива T» в «указатель на T», и его значение устанавливается чтобы указать на первый элемент в массиве. Исключениями из этого правила являются случаи, когда выражение массива отображается как операнд оператора или
&
илиsizeof
, или когда это строковый литерал, используемый в качестве инициализатора в объявлении.Таким образом, когда вы вызываете функцию с выражением массива в качестве аргумента, функция получит указатель, а не массив:
Вот почему вы не используете
&
оператор для аргументов, соответствующих "% s" вscanf()
:Из-за неявного преобразования
scanf()
получаетchar *
значение, указывающее на началоstr
массива. Это справедливо для любой функции , вызываемой с выражением массива в качестве аргумента (только о каком - либо изstr*
функций,*scanf
и*printf
функций и т.д.).На практике вы, вероятно, никогда не будете вызывать функцию с выражением массива, используя
&
оператор, как в:Такой код не очень распространен; Вы должны знать размер массива в объявлении функции, и функция работает только с указателями на массивы определенных размеров (указатель на массив из 10 элементов T отличается от указателя на массив из 11 элементов). Т).
Когда выражение массива появляется в качестве операнда
&
оператора, тип получающегося выражения - «указатель на массив из N элементов из T» илиT (*)[N]
, который отличается от массива указателей (T *[N]
) и указателя на базовый тип (T *
).При работе с функциями и указателями следует помнить следующее правило: если вы хотите изменить значение аргумента и отразить его в вызывающем коде, вы должны передать указатель на то, что вы хотите изменить. Опять же, массивы вбивают немного обезьяны, но сначала мы разберемся с обычными случаями.
Помните, что C передает все аргументы функции по значению; формальный параметр получает копию значения в фактическом параметре, и любые изменения формального параметра не отражаются в фактическом параметре. Типичным примером является функция подкачки:
Вы получите следующий вывод:
Формальные параметры
x
иy
являются отличными объектами отa
иb
, поэтому измененияx
иy
не отражаются вa
иb
. Поскольку мы хотим изменить значенияa
иb
, мы должны передать им указатели на функцию swap:Теперь ваш вывод будет
Обратите внимание, что в функции подкачки мы не меняем значения
x
иy
, а только значения, на которыеx
иy
указывают . Запись в*x
отличается от записи вx
; мы не обновляем само значениеx
, мы получаем местоположениеx
и обновляем значение в этом месте.Это в равной степени верно, если мы хотим изменить значение указателя; если мы напишем
затем мы изменяем значение входного параметра
stream
, а не то, на что онstream
указывает , поэтому изменениеstream
не влияет на значениеin
; чтобы это работало, мы должны передать указатель на указатель:Опять же, массивы бросают немного обезьяньего гаечного ключа в работу. Когда вы передаете выражение массива функции, функция получает указатель. Из-за того, как определяется подписка на массив, вы можете использовать оператор указателя для указателя так же, как вы можете использовать его для массива:
Обратите внимание, что объекты массива не могут быть назначены; то есть вы не можете сделать что-то вроде
поэтому вы должны быть осторожны, когда имеете дело с указателями на массивы; что-то вроде
не сработает
источник
Проще говоря
&
означает адрес-адрес , вы увидите, что в заполнителях функций для изменения переменной параметра, как в C, переменные параметров передаются по значению, используя амперсанд для передачи по ссылке.*
означает разыменование переменной-указателя, что означает получение значения этой переменной-указателя.В приведенном выше примере показано, как вызвать функцию
foo
с помощью передачи по ссылке, сравните с этимВот иллюстрация использования разыменования
Выше показано, как мы получили адрес
y
и присвоили его переменной-указателюp
. Тогда мы разыменовываемp
путем присоединения*
к фронту его , чтобы получить значениеp
, то есть*p
.источник
Да, это может быть довольно сложно, так как
*
используется в C / C ++ для разных целей.Если
*
появляется перед уже объявленной переменной / функцией, это означает, что:*
дает доступ к значению этой переменной (если тип этой переменной является типом указателя или перегружен*
оператором).*
имеет значение оператора умножения, в этом случае должна быть другая переменная слева от*
Если
*
появляется в объявлении переменной или функции, это означает, что эта переменная является указателем:Если
&
появляется в объявлении переменной или функции, это обычно означает, что эта переменная является ссылкой на переменную этого типа.Если
&
появляется перед уже объявленной переменной, он возвращает адрес этой переменнойКроме того, вы должны знать, что при передаче массива в функцию вы всегда должны будете также передавать размер массива этого массива, кроме случаев, когда массив является чем-то вроде cstring с нулевым символом в конце (массив символов).
источник
Когда вы объявляете переменную-указатель или параметр функции, используйте *:
Примечание: каждая объявленная переменная нуждается в своем собственном *.
Если вы хотите получить адрес значения, используйте &. Если вы хотите прочитать или записать значение в указателе, используйте *.
Массивы обычно обрабатываются как указатели. Когда вы объявляете параметр массива в функции, вы можете также легко объявить, что это указатель (это означает то же самое). Когда вы передаете массив функции, вы фактически передаете указатель на первый элемент.
Функциональные указатели - единственные вещи, которые не совсем следуют правилам. Вы можете получить адрес функции без использования &, и вы можете вызвать указатель на функцию без использования *.
источник
Я просматривал все многословные объяснения, поэтому вместо этого обратился к видео из Университета Нового Южного Уэльса за спасением. Вот простое объяснение: если у нас есть ячейка с адресом
x
и значением7
, косвенный способ запросить адрес значения7
- это&7
и косвенный способ попросить значение по адресуx
является*x
.so(cell: x , value: 7) == (cell: &7 , value: *x)
.Another способ смотреть на это:John
сидит7th seat
.the*7th seat
укажутJohn
и&John
передастaddress
/ расположение7th seat
. Это простое объяснение помогло мне и надеюсь, что оно поможет и другим. Вот ссылка на отличное видео: нажмите здесь.Вот еще один пример:
Надстройка: всегда инициализируйте указатель перед их использованием. Если нет, указатель будет указывать на что-либо, что может привести к сбою программы, поскольку операционная система не позволит вам получить доступ к памяти, которой она не владеет.
p = &x;
Мы присваиваем указателю определенное место.источник
На самом деле, у вас есть все, что вам нужно знать :-)
Я бы просто добавил следующие биты:
&
берет переменную и дает вам адрес,*
берет адрес и дает вам переменную (или содержимое).char **p
означает, чтоp
указатель на указатель наchar
.Что касается вещей, работающих по-другому, не совсем:
\0
).источник
Я думаю, что вы немного смущены. Вы должны прочитать хороший учебник / книгу по указателям.
Этот урок очень хорош для начинающих (четко объясняет, что
&
и*
есть). И да, не забудьте прочитать книгу « Указатели на С » Кеннета Рика.Разница между
&
и*
очень очевидна.Пример:
источник
Хорошо, похоже, ваше сообщение было отредактировано ...
Посмотрите, как вы можете использовать,
&
чтобы получить адрес начала структуры массива? Последующийбудет делать то же самое.
источник