Для чего в С++ нужна звездочка вот такая *?
Читай и разбирайся. Это в двух словах не расскажешь.
Если разбирёшся с «этой звёздочкой»,можешь считать, что ты в С/С++ перешёл Рубикон.
int x=10;
int *a=&x; //в «а» записали адрес переменной «х»
*a=10; //(разыменование) равно значению переменной «x» или содержимому ячейки, на которую указывает «а»
int *pa=&a;//(взятие адреса) создаём новый указатель, в который записываем адресс «а»
a=&b; //теперь в «а» хочем записать адрес переменной «в»,но отсос, такой переменной ещё нет
int b=20; //создадим переменную «в»
*a=b; //значение, имеющееся по адресу, записанному в «а» изменим на «в»,т. е. на 20.Теперь х=20
Ещё у начинающих вызывает замешательство такая фигня:
int x=10;
int *a=&x;
*a=10;
И в первом и во-втором случае есть»*а».Но в первом случае присваивается адрес, а во-втором число. Что за нелепость? Что там себе думал Страуструп? И молодой программист попадает в ступор.
Всё очень просто. Первое выражение рассматривайте так
(int *) a=&x;
В этот момент «*» не имеет отношения к получению значения. Просто объявляется переменная «а»,в которую записывается адрес переменной «х». «*» здесь говорит о том, что мы создаём указатель, а не простую переменную и всё.Такой синтаксис объявления указателей. Первое время, чтоб привыкнуть, вообще пишите так, в две строки:
int *a; //объявили указатель
a=&x;//записали в него адрес
int d=*a;//теперь d присвоили значение, которое находится в памяти по адресу, записаному в «а»
х==10;
a==0x33787974(или что-то похожее) ;
d==10;
* используется по-разному. зависит от места применения.
* оператор умножения
int a, b,c;
c = a * b; // оператор умножения a и b
с *= а; // оператор умножения с присваиванием, равносильно c = c * a;
* в определении типа переменной
int a, *b, **c;
a — переменная типа int,
b — переменная типа указатель на int
c — переменная типа указатель на указатель на int
указатель- это переменная, содержащая адрес другой переменной
* оператор разыменования указателя.
Если переменная-указатель содержит адрес другой переменной, то чтобы использовать переменную на которую «смотрит» указатель, указатель нужно разыменовать.
int a, *b;
b = &a;// инициализация указателя, теперь b смотрит на a;
*b = 20;// переменной на которую смотрит b (т. е. — a) присвоить значение 20
int c = *b; // c присвоить значение переменной, на которую смотрит b
Как ставится звездочка при создании указателя в си? [дубликат]
Как ставится звездочка * при создании указателя? Точнее в чем разница между:
- char* str;
- char * str;
- char *str;
На что влияет место в котором находится * ?
![]()
Пробельные символы допустимо ставить в любом месте, где он не разрывает ключевое слово, идентификатор или константу.
Все варианты ниже полностью эквивалентны:
Но есть некоторая тонкость. Если посмотреть на синтаксис объявления нескольких переменных:
то будет видно, что «звездочка» является скорее модификатором переменной, чем модификатором типа. Чтобы подчеркнуть этот факт, рекомендуется всегда писать «звездочку» около переменной. Такая привычка позволяет избежать глупых ошибок:
![]()
Ни на что не влияет. Но есть подводный камень:
В этом примере только str1 является указателем. str2 — просто char. Поэтому я обычно делаю так:
Теперь обе переменные являются указателями.
![]()
Всё ещё ищете ответ? Посмотрите другие вопросы с метками c указатели или задайте свой вопрос.
Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2022.6.10.42345
Нажимая «Принять все файлы cookie», вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Урок 8: «Первое знакомство с указателями»
Вы уже должны уметь писать простейшие программы на C++. Теперь вы знаете, что такое массивы, функции, переменные и как все это использовать. С этого урока можно сказать, что начинается вторая часть изучения, немного сложнее предыдущей.
В этом уроке мы коснемся, правда пока еще поверхностно, с такими средствами C, как указатели и ссылки. Это очень важная тема, поэтому внимательно читайте урок.
Указатель – это переменная, содержащая адрес памяти, в которой содержится другая переменная. Как это понять? Вы уже знаете, что для каждой переменной вашей программы компилятор выделяет место в памяти. Так вот, указатель как раз содержит адрес этого места. Давайте рассмотрим это на примере.
У нас есть число 27 типа int. Мы используем переменную a для хранения этого числа. В стеке программы выделилось место для хранения этой переменной (что такое стек мы рассмотрим в уроках с динамическими структурами данных). Графически это можно представить так:
Я сильно абстрагируюсь, но примерно в памяти это будет так. Как видите, у меня на рисунке наша переменная содержится во второй ячейке. Естественно, что компьютер переведет для себя в 16 ричный код адрес этой ячейки. И теперь, если воспользоваться указателем и присвоить ему значение этого адреса, то мы получим доступ к этой ячейке. Немного непонятно, не так ли?
Дело в том, что C++, как расширение своего предшественника C, является, как выразился Денис Ричи (создатель C), языком «среднего уровня». В компьютерной литературе вы тщетно можете искать определение этого термина –его просто нет. Тем не менее, C был компромиссом между низкоуровневым языком и высокоуровневым. Дело в том, что раньше системные программы писались на ассемблере, где напрямую можно обращаться к регистрам процессора (регистр в ассемблере это что-то типа переменной в широком смысле этого слова). Если вы никогда не писали программы на ассемблере, поздравляю – вы не убили часть своей жизни на бесполезное занятие. Почему я так говорю? Да просто потому, что ассемблерный код в десятки раз длиннее того же сишного и писать его все же сложнее. Однако операционная система с драйверами это не все, что нужно для комфортного пользования компьютером. Нужны были прикладные программы, писать которые на ассемблере чистой воды безумие. Для этих целей использовался высокоуровневый язык.
Когда была написана операционная система Unix, остро встал вопрос о портировании ее на различные компьютеры (ассемблерный код был привязан только к тому типу процессора, для которого был написан). И тогда встал вопрос о создании языка, на котором можно писать и операционные системы с драйверами, и прикладные программы. Причем все это должно делаться с одинаковым уровнем сложности. В конечном счете был создан С, а потом и С++.
Так вот, указатели перекочевали в C++ из C. Я уже упомянул тот факт, что драйвера и операционные системы обращаются к регистрам процессора. Конечно, можно это сделать при помощи ассемблерных вставок, разумно включенными в язык, а можно использовать указатели, содержащие адрес этих регистров. Алгоритм тогда сводился к следующему – мы получаем адрес ячейки с данными и меняем значение ячейки ( не адреса!) на нужное. Об этом мы поговорим гораздо позже.
Чтобы не быть голословным, продемонстрирую это на примере. Но для начала давайте разберемся с синтаксисом указателей.
В C, равно как и в C++, указатель задается так:
тип переменной* имя_указателя.
Причем звездочка может стоят сразу как после типа, так и перед именем указателя. Это не будет ошибкой. Просто программисты пишут по-разному. Этот пример дань Паскалю. Лично я раньше ставил звездочку перед именем переменной, но потом почему-то стал ставить ее после типа. Важно также ставить префикс перед именем переменной, чтобы знать, что используется указатель. Обычно ставят символ p или ptr, здесь роли не играет. Просто вам самим нужно знать, что это указатель. Еще один важный момент — указатель должен быть именно того же типа, как и переменная, адрес которой вы хотите в него поместить. Представьте себе, что вам нужно купить джинсы 48 размера, а вам настойчиво предлагают 46 или 44. Иными словами, данные просто не влезут в такой указатель.
Давайте теперь немного поясню. Во второй строке я объявил указатель типа int и там же присвоил ему адрес переменной a при помощи оператора изъятия адреса &. Я бы мог написать так:
Просто тот вариант более удобен. Чтобы показать, что сейчас содержится в памяти, я вывел содержимое указателя. А теперь вернемся к тому замечательному свойству, позволяющему через указатель манипулировать данными в ячейке памяти. Для того, чтобы изменить данные, указатель нужно разыменовать. Для этого перед именем указателя нужно поставить *. Теперь мы можем присвоить любое значение. В переменной a сразу же отразятся эти изменения, для чего я и вывел ее содержимое. Поэкспериментируйте. Забегая далеко вперед, все читерские программы, изменяющие значение переменных в играх, делают это при помощи указателей. Вот такое полезное применение. Но не нужно думать, что на этом использование указателей ограничивается.
Мы знаем, что в функцию для гибкости расчетов удобно передавать параметры. Причем параметры передаются по значению и по ссылке. В уроке про функции я этот момент искусственно опустил, но теперь полностью поясню.
Когда вы передаете параметр по значению, компилятор создает копию это переменной и манипулирует уже ей. То есть, если мы передадим в функцию нашу переменную a, содержащую число 27, то компилятор создаст клона этой переменной. Но на это уходит время процессора и глупо расходуется память. Конечно, это не критично, если у вас там используются примитивные типы данных. Но вы же можете передавать структуры или классы в функцию, а они могут занимать большие размеры памяти и процессору необходимо будет время на создание копии такой структуры или класса. Поэтому в таких целях используются параметры по ссылке.
Механизм работы подобного параметра прост – вместо копии переменной мы передаем в функцию ее адрес. Это очень экономит время процессора и часто весьма удобно. Конечно, возникает вопрос о том, что программист может нечаянно изменить данные в этом указателе. Чтобы этого избежать, используется классификатор const в параметре:
Пока этот код не берите во внимание. Я сейчас поговорю еще об одной возможности работы с адресом переменной. Речь пойдет здесь о ссылке.
Ссылка – это не более, чем псевдоним переменной. По сути, это тот же адрес. Применяется ссылка при передаче параметра по ссылке. Честно говоря, о другом применении ссылок я даже и не знаю. Если можете привести такой пример, буду признателен.
Естесственно, что ссылка предваряется оператором изъятия адреса &, о котором я уже говорил. Давайте теперь я покажу сигнатуру функции, в которой передается параметр по ссылке:
Как видите, принцип почти тот же самый, что и с указателями. Теперь с a можно делать все, что душе угодно. Однако, еще раз оговорюсь, лично я ссылки не использую, так же как и мои коллеги. Достаточно указателей. Для сравнения, вышеупомянутая подпрограмма с использованием указателей будет выглядеть так:
При использовании указателей в параметре мы передаем в качестве параметра адрес переменной a. Это почти тоже самое, что и с ссылкой. Важно просто не забывать ставить амперсанд (&).
Пока на этом урок закончен. В следующем уроке мы рассмотрим более углубленно указатели. А пока отдохните.