C++ — Указатели
C ++ указатели легко и интересно учиться. Некоторые задачи C ++ легче выполняются с указателями, а другие задачи C ++, такие как распределение динамической памяти, не могут выполняться без них.
Как вы знаете, каждая переменная является местом памяти, и каждая ячейка памяти имеет свой адрес, который можно получить, используя оператор ampersand (&), который обозначает адрес в памяти. Рассмотрим следующее, которое будет печатать адрес определенных переменных —
#include <iostream>
using namespace std;
int main () {
int var1;
char var2[10];
cout << "Address of var1 variable: ";
cout << &var1 << endl;
cout << "Address of var2 variable: ";
cout << &var2 << endl;
return 0;
}
Когда приведенный выше код компилируется и выполняется, он производит следующий результат:
Address of var1 variable: 0xbfebd5c0 Address of var2 variable: 0xbfebd5b6
Что такое указатели?
Указатель является переменной, значение которого является адрес другой переменной. Как и любая переменная или константа, вы должны объявить указатель, прежде чем сможете с ним работать. Общая форма объявления переменной указателя —
type *var-name;
Здесь тип — это базовый тип указателя; он должен быть допустимым типом C ++, а var-name — это имя переменной-указателя. Звездочкой, которую вы использовали для объявления указателя, является та же самая звездочка, которую вы используете для умножения. Однако в этом утверждении звездочка используется для обозначения переменной как указателя. Ниже приведена действительная декларация указателя —
int *ip; // pointer to an integer
double *dp; // pointer to a double
float *fp; // pointer to a float
char *ch // pointer to character
Фактический тип данных для всех указателей, будь то целое число, float, character или other, является тем же самым, длинным шестнадцатеричным числом, которое представляет адрес памяти. Единственное различие между указателями разных типов данных — это тип данных переменной или константы, на которые указывает указатель.
Использование указателей в C ++
Существует несколько важных операций, которые мы будем делать с указателями очень часто. (a) Мы определяем переменную указателя. (b)Назначьте адрес переменной указателю. (c) Наконец, получите доступ к значению по адресу, доступному в переменной указателя. Это делается с помощью унарного оператора *, который возвращает значение переменной, расположенную по адресу, указанному его операндом. В следующем примере используются эти операции —
#include <iostream>
using namespace std;
int main () {
int var = 20; // actual variable declaration.
int *ip; // pointer variable
ip = &var; // store address of var in pointer variable
cout << "Value of var variable: ";
cout << var << endl;
// print the address stored in ip pointer variable
cout << "Address stored in ip variable: ";
cout << ip << endl;
// access the value at the address available in pointer
cout << "Value of *ip variable: ";
cout << *ip << endl;
return 0;
}
Когда приведенный выше код скомпилирован и исполнен, он производит результат следующим образом:
Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of *ip variable: 20
Указатели в C ++
У указателей есть много, но простых понятий, и они очень важны для программирования на С ++. Существует несколько важных понятий указателей, которые должны быть понятны программисту на C ++ —
Нулевые указатели
C ++ поддерживает нулевой указатель, который является константой со значением нуля, определенным в нескольких стандартных библиотеках.
Арифметика указателей
Существует четыре арифметических оператора, которые могут использоваться для указателей: ++, -, +, —
Указатели против массивов
Существует тесная связь между указателями и массивами.
Массив указателей
Вы можете определить массивы для хранения нескольких указателей.
Указатель на указатель
C ++ позволяет иметь указатель на указатель и так далее.
Передача указателей на функции
Передача аргумента по ссылке или по адресу позволяет включить переданный аргумент, который будет изменен вызывающей функцией вызываемой функцией.
Возвращаемый указатель из функций
C ++ позволяет функции возвращать указатель на локальную переменную, статическую переменную и динамически распределенную память.
что такое указатель, и что он делает?
Добавлено 27 мая 2019 в 13:41
Данная статья поможет вам понять указатели, которые являются интересным и важным аспектом языка C.
С точки зрения инженера-электронщика, который пишет прошивки для встраиваемых систем, указатели не являются необходимым инструментом. Однако я собираюсь рассказать о них сейчас, а не позже в этой серии статей, потому что они тесно связаны с массивами, которые мы обсуждали в предыдущей статье. Кроме того, указатели помогают укрепить ваше понимание взаимосвязи между кодом и аппаратным обеспечением.
Я написал немало прошивок, и у меня осталось всего несколько случайных воспоминаний об использовании указателей. Однако я рад, что понимаю их, потому что, когда ситуация требует указателей, я бы предпочел использовать их, а не какое-то простое неэффективное решение по умолчанию.
Что такое указатель?
Указатель – это переменная. Как и другие переменные, он имеет тип данных и идентификатор. Однако указатели используются таким образом, которой принципиально отличается от того, как мы используем «нормальные» переменные, и при объявлении мы должны добавить звездочку, чтобы сообщить компилятору, что данная переменная должна рассматриваться как указатель.char *RxByte_ptr; int *ADCValue_ptr;
Идентификатор не обязательно должен содержать символы, которые помечают переменную как указатель (такие как «ptr«). Тем не менее, я очень рекомендую использовать эту практику. Это поможет вам сохранить ваши мысли более организованными, и если у вас все указатели будут помечены таким образом, другим инженерам будет легче понять ваш код.
Что делает указатель?
Он указывает. Более конкретно, он указывает на данные другой переменной или на данные, которые хранятся в памяти, но не связаны с переменной.
Рисунок 1 – На что указывает указательОбычно мы думаем о переменной как о чем-то, что хранит данные, а под «данным» мы подразумеваем информацию, которая будет использоваться в вычислениях, или отправляться на другое устройство, или загружаться в регистр конфигурации, или использоваться для управления пикселями LCD дисплея. Указатель – это переменная, но она не используется для хранения такого типа данных. Вернее указатель хранит адрес памяти.
Рисунок 2 – Данные о температуре хранятся в переменной, расположенной по адресу 0x01, а синяя переменная является указателем, который содержит адрес, по которому хранятся данные о температуреВозможно, именно в этот момент некоторые люди начинают немного путаться, и я думаю, что это происходит потому, что легко упустить из виду физическую реальность памяти процессора. Блок памяти представляет собой набор цифровых ячеек памяти, которые организованы в группы. В случае 8-разрядного процессора каждая группа ячеек памяти соответствует одному байту. Единственный способ отличить одну группу от другой – это адрес, а этот адрес – просто число. Указатель – это переменная, в которой хранится число, но это число интерпретируется как адрес, т.е. как значение, указывающее точное местоположение в памяти.
Подкрепим эту концепцию краткой аналогией. Представьте, что я стою в библиотеке, и кто-то подходит ко мне и говорит: «Кто такой Ричард Львиное Сердце?». Если я отвечаю, говоря: «Король Англии с 1189 по 1199 года», я похож на обычную переменную. Я предоставляю информацию, данные, которые хочет получить человек. И напротив, если я отвечаю, указывая на книгу под названием «Монархи средневековой Англии», я действую как указатель. Вместо того чтобы предоставлять нужные данные, я указываю, где именно эти данные можно найти. Я до сих пор храню полезную информацию, но эта информация – это не сам факт, а место, где человек может получить доступ к этому факту.
Понятие типов данных указателей
Как вы могли заметить в приведенных выше примерах, указатели объявляются с типом данных. Возможно, это усугубляет сложность понимания, что такое указатель. Если указатель – это просто число, соответствующее адресу ячейки памяти, то как могут использоваться разные типы данных? Например, если ваш микроконтроллер имеет 4 КБ RAM, как вы можете иметь указатель с типом данных char
? Максимальное значение unsigned char
составляет 255; что произойдет, если этот указатель должен указывать на переменную, расположенную по адресу памяти 3000?
Ключ к пониманию этой проблемы заключается в следующем: тип данных указателя не указывает, сколько байтов используется для хранения его значения. Скорее, число байтов, используемых для хранения значения указателя, соответствует количеству адресов памяти, к которым необходимо получать доступ, независимо от типа данных указателя. Кроме того, размер указателя определяется компилятором и непосредственно не виден программисту.
Рассмотрим следующую диаграмму:
Рисунок 3 – Представления в памяти переменной и указателя на эту переменнуюДопустим, мы используем жалкий микроконтроллер с оперативной памятью всего 11 байтов. Диапазон значений, предлагаемых 8-разрядным числом, составляет от 0 до 255, поэтому один байт памяти более чем достаточен для представления всех возможных областей памяти в этом устройстве.
Диаграмма подчеркивает тот факт, что даже переменная, объявленная как long
, может быть доступна через однобайтовый указатель. Синяя переменная – это указатель, который содержит адрес 32-битной переменной Seconds_Cnt
. Эта переменная использует четыре байта памяти, но адрес переменной (который в этом примере соответствует младшему значащему байту) всегда будет числом, равным или меньшим 0x0A
. Указатель должен быть объявлен с типом данных long
, потому что он используется вместе с переменными long
, но сам указатель потребляет один байт памяти, а не четыре.
Продолжение следует…
Для такой темы, как указатели, одной статьи просто не хватает. Теперь вы знаете, что такое указатель, и основные возможности, которые он предоставляет в контексте программирования на C. В следующей статье мы сможем узнать, как они действуют, то есть, как на самом деле использовать указатели в ваших проектах встроенного программного обеспечения (прошивок).
Оригинал статьи:
- Robert Keim. Pointers in C Programming: What Is a Pointer and What Does It Do?
Теги
MCUВысокоуровневые языки программированияНазад
Оглавление
Вперед
Что такое указатели в C++?
Группа образовательных ответов
Устали от LeetCode? 😩
Изучите 24 паттерна, чтобы решить любой вопрос на собеседовании по программированию, не заблудившись в лабиринте практических задач в стиле LeetCode. Практикуйте свои навыки в практической среде кодирования, не требующей настройки. 💪
В C++ указатель содержит адрес объекта, хранящегося в памяти. Затем указатель просто «указывает» на объект. Тип объекта должен соответствовать типу указателя.
введите *имя; // указывает на значение указанного типа
тип
относится к типу данных объекта, на который указывает наш указатель, а имя
— это просто метка указателя. Символ *
указывает, что эта переменная на самом деле является указателем. Вот пример:
int *p; // целочисленный указатель строка *q; // указатель строки
Символ и
указывает, что мы сохраняем адрес переменной, следующей за ним.
Символ *
позволяет нам получить доступ к значению.
#include
использование пространства имен std;
int main() {
int var = 10;
интервал *p;
p = &var; // p указывает на адрес var
cout << "Адрес, хранящийся в p: " << p << endl;
cout << "Значение, указывающее на: " << *p << endl;
*р = 15; // обновить значение p
cout << "Новое значение var: " << var << endl; // переменная обновляется!
вар = 20; // значение var обновлено
cout << "Новое значение *p и var: " << *p; // p также был обновлен!
}
Динамическая память
Итак, зачем нам нужны указатели, когда у нас уже есть обычные переменные? Ну, с указателями у нас есть возможность создавать новые объекты в динамической памяти , а не в статической памяти. Указатель может создать новый объект в динамической памяти, используя новая команда
.
#include
использование пространства имен std;
int main() {
int *p = new int; // динамическая память зарезервирована для целого числа
*p = 10; // объекту присваивается значение 10
cout << "Значение объекта p указывает на: " << *p << endl;
интервал *q = р; // оба указателя указывают на один и тот же объект
cout << "Значение объекта q указывает на: " << *q << endl;
}
Синтаксис | Назначение |
---|---|
инт *р | Объявляет указатель p |
р = новый интервал | Создает целочисленную переменную в динамической памяти и помещает ее адрес в p |
р = новый интервал [5] | Создает динамический массив размером 5 и помещает адрес его первого индекса в p |
р = &var | Очки p к var переменная |
*р | Доступ к значению объекта p указывает на |
*р = 8 | Обновляет значение объекта p точек до |
р | Доступ к адресу памяти объекта p указывает на |
СВЯЗАННЫЕ ТЕГИ
c++
dynamic
Copyright © 2022 Educative, Inc.
Объявления указателей | Microsoft Узнайте
Обратная связь Редактировать
Твиттер LinkedIn Фейсбук Эл. адрес
- Статья
- 4 минуты на чтение
Объявление указателя называет переменную-указатель и указывает тип объекта, на который указывает переменная. Переменная, объявленная как указатель, содержит адрес памяти.
Syntax
declarator :
pointer opt direct-declarator
direct-declarator :
identifier
( declarator )
direct-declarator [ константное-выражение opt ]
прямой-декларатор ( список-типов-параметров )
direct-declarator ( identifier-list opt )
pointer :
* type-qualifier-list opt
* type- список-квалификаторов opt указатель
список-квалификаторов : 0 список-квалификаторов 40003 Спецификатор типа задает тип объекта, который может быть любым базовым, структурным или типом объединения. Переменные-указатели также могут указывать на функции, массивы и другие указатели. (Информацию об объявлении и интерпретации более сложных типов указателей см. в разделе Интерпретация более сложных деклараторов.) Сделав спецификатор типа Квалификатор типа может быть либо Декларатор называет переменную и может включать модификатор типа. Например, если декларатор представляет массив, тип указателя изменяется и становится указателем на массив. Вы можете объявить указатель на структуру, объединение или тип перечисления до определения структуры, объединения или типа перечисления. Вы объявляете указатель, используя тег структуры или объединения, как показано в примерах ниже. Такие объявления разрешены, потому что компилятору не нужно знать размер структуры или объединения, чтобы выделить место для переменной-указателя. Следующие примеры иллюстрируют объявления указателей. Указатель сообщения указывает на переменную с типом Массив указателей состоит из 10 элементов; каждый элемент является указателем на переменную типа Переменная указатель указывает на массив из 10 элементов. Каждый элемент в этом массиве имеет тип Указатель x можно изменить, чтобы он указывал на другое значение Переменная y в этих объявлениях объявляется как постоянный указатель на значение В этом примере объявляются две переменные-указатели, next и previous , которые указывают на тип структуры list . Это объявление может появиться перед определением типа структуры list (см. следующий пример), если определение типа list имеет ту же видимость, что и объявление. Переменная строка имеет тип структуры с именем list . Тип структуры list состоит из трех членов: первый член — указатель на значение Переменная запись имеет тип структуры идентификатор .
квалификатор типов
квалификатор типов квалификатор типов недействительным
, вы можете отложить определение типа, к которому относится указатель. Такой элемент называется «указатель на void
» и записывается как void *
. Переменная, объявленная как указатель на void , может использоваться для указания на объект любого типа. Однако для выполнения большинства операций над указателем или над объектом на который он указывает, тип, на который он указывает, должен быть явно указан для каждой операции (переменные типа char
* и типа void
* совместимы по присваиванию без приведения типа. ) Такое преобразование может быть выполнено с помощью приведения типов (дополнительную информацию см. в разделе Преобразования приведения типов).0003 const
, либо volatile
, либо обоими. Они указывают, соответственно, что указатель не может быть изменен самой программой ( const
) или что указатель может быть законно изменен каким-либо процессом, не зависящим от программы ( volatile
). (Дополнительную информацию о const
и volatile 9 см. в квалификаторах типов.0016
.) Примеры
символ *сообщение; /* Объявляет переменную-указатель с именем message */
char
. int *указатели[10]; /* Объявляет массив указателей */
int
. интервал (*указатель)[10]; /* Объявляет указатель на массив из 10 элементов */
int
. int const *x; /* Объявляет переменную-указатель x,
к постоянному значению */
int
, но значение, на которое он указывает, изменить нельзя. const int some_object = 5 ;
интервал другой_объект = 37;
int *const y = &fixed_object;
int volatile *const z = &some_object;
int *const volatile w = &some_object;
int
. Значение, на которое он указывает, может быть изменено, но сам указатель всегда должен указывать на одно и то же место: адрес fixed_object . Точно так же z является постоянным указателем, но также объявлено, что он указывает на 9.0009 int
, значение которого не может быть изменено программой. Дополнительный спецификатор volatile
указывает, что хотя значение const int , на которое указывает z , не может быть изменено программой, оно может быть законно изменено процессом, запущенным одновременно с программой. Объявление w указывает, что программа не может изменить значение, на которое указывает указатель, и что программа не может изменить указатель. список структур *следующий, *предыдущий; /* Использует тег для списка */
список структур
{
символ *токен;
счет;
список структур *next;
} линия;
char
, второй — значение int
, а третий — указатель на другую структуру list . идентификатор структуры
{
беззнаковое целое число id_no;
имя структуры *pname;
} записывать;