Pointer to c что это

от admin

Указатели в C++

Указатель (пойнтер, англ. pointer) — это переменная, содержащая адрес другой переменной. Тип данных pointer равен 4 байта. Указатели очень широко используются в языке C. Это происходит отчасти потому, что иногда они дают единственную возможность выразить нужное действие, а отчасти потому, что они обычно ведут к более компактным и эффективным программам, чем те, которые могут быть получены другими способами.

Так как указатель содержит адрес объекта, это дает возможность "косвенного" доступа к этому объекту через указатель.

Указатели и массивы

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

определяет массив размера 10, т.е. набор из 10 последовательных объектов, называемых a[0], a[1], …, a[9]. Запись a[i] соответствует элементу массива через i позиций от начала. Если pa — указатель целого, описанный как

приводит к тому, что pa указывает на нулевой элемент массива a. Это означает, что pa содержит адрес элемента a[0]. Теперь присваивание

будет копировать содержимое a[0] в x.

Если ра указывает на некоторый определенный элемент массива a, то по определению pa+1 указывает на следующий элемент, и вообще pa-i указывает на элемент, стоящий на i позиций до элемента, указываемого pa, а pa+i на элемент, стоящий на i позиций после. Таким образом, если pa указывает на a[0], то *(pa+1)

ссылается на содержимое a[1], pa+i — адрес a[i], а *(pa+i) — содержимое a[i].

Эти замечания справедливы независимо от типа переменных в массиве a. Суть определения "добавления 1 к указателю", а также его распространения на всю арифметику указателей, состоит в том, что приращение масштабируется размером памяти, занимаемой объектом, на который указывает указатель. Таким образом, i в pa+i перед прибавлением умножается на размер объектов, на которые указывает pa.

Очевидно существует очень тесное соответствие между индексацией и арифметикой указателей. В действительности компилятор преобразует ссылку на массив в указатель на начало массива. В результате этого имя массива является указательным выражением. Отсюда вытекает несколько весьма полезных следствий. Так как имя массива является синонимом местоположения его нулевого элемента, то присваивание pa = &a[0]

можно записать как pa = a.

Еще более удивительным, по крайней мере на первый взгляд, кажется тот факт, что ссылку на a[i] можно записать в виде *(a+i). При анализировании выражения a[i] в языке C оно немедленно преобразуется к виду *(a+i); эти две формы совершенно эквивалентны. Если применить операцию & к обеим частям такого соотношения эквивалентности, то мы получим, что &a[i] и a+i тоже идентичны: a+i — адрес i-го элемента от начала a. С другой стороны, если pa является указателем, то в выражениях его можно использовать с индексом: pa[i] идентично *(pa+i). Короче, любое выражение, включающее массивы и индексы, может быть записано через указатели и смещения и наоборот, причем даже в одном и том же утверждении.

Когда имя массива передается функции, то на самом деле ей передается местоположение начала этого массива. Внутри вызванной функции такой аргумент является точно такой же переменной, как и любая другая, так что имя массива в качестве аргумента действительно является указателем, т.е. переменной, содержащей адрес. Мы можем использовать это обстоятельство для написания нового варианта функции strlen, вычисляющей длину строки: /* возвращает длину строки s */

Операция увеличения s совершенно законна, поскольку эта переменная является указателем, s++ никак не влияет на символьную строку в обратившейся к strlen функции, а только увеличивает локальную для функции strlen копию адреса.

Описания формальных параметров в определении функции в виде char s[];

совершенно эквивалентны; какой вид описания следует предпочесть, определяется в значительной степени тем, какие выражения будут использованы при написании функции. Если функции передается имя массива, то в зависимости от того, что удобнее, можно полагать, что функция оперирует либо с массивом, либо с указателем, и действовать далее соответвующим образом. Можно даже использовать оба вида операций, если это кажется уместным и ясным.

Имя массива — это константа, представляющая собой указатель на 0-ой элемент массива. Этот указатель отличается от обычных тем, что его нельзя изменить (установить на другую переменную), поскольку он сам хранится не в переменной, а является просто некоторым постоянным адресом.

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

Операция & перед одиноким именем массива не нужна и недопустима! Такое родство указателей и массивов позволяет нам применять операцию * к имени массива: value = *array; означает то же самое, что и value = array[0];

Как описывать ссылки (указатели) на двумерные массивы?

Как описывать ссылки (указатели) на двумерные массивы? Рассмотрим такую программу:

Указателем здесь является ptr. Отметим, что у него задана размерность по второму измерению: Second, именно для того, чтобы компилятор мог правильно вычислить двумерные индексы.

Попробуйте сами объявить

и увидеть, к каким невеселым эффектам это приведет (компилятор, кстати, будет ругаться; но есть вероятность, что он все же странслирует это для вас. Но работать оно будет плачевно). Попробуйте также использовать ptr[x][y].

Обратите также внимание на инициализацию строк в нашем примере. Строка "ABC." равносильна объявлению

Указатели на функции

Например, используется в функции: Быстрая сортировка (англ. quicksort), часто называемая qsort. В функции qsort указатель на функцию применяется для указания способа сортировки.

Прежде чем вводить указатель на функцию, напомним, что каждая функция характеризуется типом возвращаемого значения, именем и сигнатурой. Напомним, что сигнатура определяется количеством, порядком следования и типами параметров. Иногда говорят, что сигнатурой функции называется список типов ее параметров.

А теперь путём последовательности утверждений придем к обсуждению темы данного раздела урока.

1. При использовании имени функции без последующих скобок и параметров имя функции выступает в качестве указателя на эту функцию, и его значением служит адрес размещения функции в памяти.

2. Это значение адреса может быть присвоено некоторому указателю, и затем уже этот новый указатель можно применять для вызова функции.

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

4. Указатель на функцию определяется следующим образом:

Например: int (*func1Ptr) (char); — определение указателя func1Ptr на функцию с параметром типа char, возвращающую значение типа int.

Примечание: Будьте внимательны. Если приведенную синтаксическую конструкцию записать без первых круглых скобок, т.е. в виде int *fun (char); то компилятор воспримет ее как прототип некой функции с именем fun и параметром типа char, возвращающей значение указателя типа int *. Второй пример: char * (*func2Ptr) (char * ,int); — определение указателя func2Ptr на функцию с параметрами типа указатель на char и типа int, возвращающую значение типа указатель на char.

Иллюстрируем на практике. В определении указателя на функцию тип возвращаемого значения и сигнатура (типы, количество и последовательность параметров) должны совпадать с соответствующими типами и сигнатурами тех функций, адреса которых предполагается присваивать вводимому указателю при инициализации или с помощью оператора присваивания. В качестве простейшей иллюстрации сказанного приведем программу с указателем на функцию:

Результат выполнения программы:

Здесь значением имени_указателя служит адрес функции, а с помощью операции разыменования * обеспечивается обращение по адресу к этой функции. Однако будет ошибкой записать вызов функции без скобок в виде *ptr();. Дело в том, что операция () имеет более высокий приоритет, нежели операция обращения по адресу *. Следовательно, в соответствии с синтаксисом будет вначале сделана попытка обратиться к функции ptr(). И уже к результату будет отнесена операция разыменования, что будет воспринято как синтаксическая ошибка.

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

При присваивании указателей на функции также необходимо соблюдать соответствие типов возвращаемых значений функций и сигнатур для указателей правой и левой частей оператора присваивания. То же справедливо и при последующем вызове функций с помощью указателей, т.е. типы и количество фактических параметров, используемых при обращении к функции по адресу, должны соответствовать формальным параметрам вызываемой функции. Например, только некоторые из следующих операторов будут допустимы:

Следующая программа отражает гибкость механизма вызовов функций с помощью указателей.

Результаты выполнения программы:

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

Массивы указателей на функции. Указатели на функции могут быть объединены в массивы. Например, float (*ptrArray[4]) (char) ; — описание массива с именем ptrArray из четырех указателей на функции, каждая из которых имеет параметр типа char и возвращает значение типа float. Чтобы обратиться, например, к третьей из этих функций, потребуется такой оператор:

Как обычно, индексация массива начинается с 0, и поэтому третий элемент массива имеет индекс 2.

Массивы указателей на функции удобно использовать при разработке всевозможных меню, точнее программ, управление которыми выполняется с помощью меню. Для этого действия, предлагаемые на выбор будущему пользователю программы, оформляются в виде функций, адреса которых помещаются в массив указателей на функции. Пользователю предлагается выбрать из меню нужный ему пункт (в простейшем случае он вводит номер выбираемого пункта) и по номеру пункта, как по индексу, из массива выбирается соответствующий адрес функции. Обращение к функции по этому адресу обеспечивает выполнение требуемых действий. Самую общую схему реализации такого подхода иллюстрирует следующая программа для "обработки файлов":

Пункты меню повторяются, пока не будет введен номер 5 — закрытие.

Friendhosting — Разумные цены на хостинг

VDS/VPS сервер от 3.49€ в месяц. Много ресурсов. Высокая надежность. Гибкое управление. Удобная оплата. Настройка под вас!

Антидетект браузер Dolphin бесплатно до 10 профилей

Dolphin разработан для работы с такими сложными ресурсов, как Google, Facebook и Coinlist.

Английский для IT‑специалистов по Skype

Персональные занятия по разумным ценам. 80% разговорной практики. Персональный график!

Pointer declaration

Указатель-это тип объекта,который ссылается на функцию или объект другого типа,возможно,добавляя классификаторы.Указатель может также не ссылаться ни на что,что обозначается специальным значением нулевого указателя.

Syntax

В грамматике объявления указателя последовательность спецификаторов типа обозначает тип, на который указывает указатель (который может быть типом функции или объекта и может быть неполным), а декларатор имеет форму:

* attr-spec-seq(optional)qualifiers(optional)declarator

где декларатором может быть идентификатор,дающий имя объявляемому указателю,в том числе и другой декларатор указателей (который будет указывать указатель на указатель):

Квалификаторы, которые появляются между * и идентификатором (или другим вложенным декларатором), определяют тип указателя, который объявляется:

attr-spec-seq(C23) — это необязательный список атрибутов , применяемых к объявленному указателю.

Explanation

Указатели используются для косвенного обращения, что является повсеместной техникой программирования; они могут использоваться для реализации семантики передачи по ссылке, для доступа к объектам с динамической длительностью хранения , для реализации «необязательных» типов (с использованием значения нулевого указателя), агрегирования отношений между структурами, обратных вызовов (с использованием указателей на функции), универсальных интерфейсов (используя указатели для аннулирования) и многое другое.

Указатели на объекты

Указатель на объект может быть инициализирован с помощью результата оператора address-of, примененного к выражению типа объекта (которое может быть неполным):

Указатели могут отображаться как операнды для оператора косвенности (унарный * ), который возвращает значение l, идентифицирующее объект, на который указывает указатель:

Указатели на объекты типа struct и union также могут отображаться как левые операнды доступа к члену через оператор указателя -> .

Из -за неявного преобразования массива в указатель указатель на первый элемент массива может быть инициализирован выражением типа массива:

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

Операторы сравнения определены для указателей на объекты в некоторых ситуациях: два указателя, которые представляют один и тот же адрес, сравниваются одинаково, два значения нулевого указателя сравниваются одинаково, указатели на элементы одного и того же массива сравниваются так же, как индексы массива этих элементов, и указатели на члены структуры сравниваются в порядке объявления этих членов.

Многие реализации также обеспечивают строгое полное упорядочение указателей случайного происхождения, например, если они реализованы как адреса в непрерывном («плоском») виртуальном адресном пространстве.

Указатели на функции

Указатель на функцию можно инициализировать с помощью адреса функции. Из -за преобразования функции в указатель оператор address-of является необязательным:

В отличие от функций,указатели на функции являются объектами и,таким образом,могут храниться в массивах,копироваться,присваиваться,передаваться другим функциям в качестве аргументов и т.д.

Указатель на функцию можно использовать в левой части оператора вызова функции ; это вызывает указанную функцию:

При разыменовании указателя функции появляется обозначение функции для функции,на которую указывает указатель:

Операторы сравнения на равенство определены для указателей на функции (они сравнивают равные, если указывают на одну и ту же функцию).

Поскольку совместимость типов функций игнорирует квалификаторы верхнего уровня параметров функции, указатели на функции, параметры которых отличаются только своими квалификаторами верхнего уровня, взаимозаменяемы:

Указатели на аннулирование

Указатель на объект любого типа может быть неявно преобразован в указатель на void (необязательно, const или volatile -qualified), и наоборот:

Указатели на void используются для передачи объектов неизвестного типа, что является обычным явлением в универсальных интерфейсах: malloc возвращает void* , qsort ожидает предоставленный пользователем обратный вызов, который принимает два аргумента const void* . pthread_create ожидает предоставленный пользователем обратный вызов, который принимает и возвращает void* . Во всех случаях вызывающая сторона обязана преобразовать указатель в правильный тип перед использованием.

Null pointers

Указатели каждого типа имеют специальное значение,известное как нулевое значение указателя такого типа.Указатель,значение которого равно нулю,не указывает на объект или функцию (разыменование нулевого указателя является неопределенным поведением),а сравнивает его со всеми указателями одного типа,значением которых также является null .

Чтобы инициализировать указатель нулевым значением или присвоить нулевое значение существующему указателю, может использоваться константа нулевого указателя ( NULL или любая другая целочисленная константа со значением ноль). статическая инициализация также инициализирует указатели к их нулевым значениям.

Нулевые указатели могут указывать на отсутствие объекта или могут использоваться для указания других типов состояний ошибки. В общем, функция, которая получает аргумент указателя, почти всегда должна проверять, является ли значение нулевым, и обрабатывать этот случай по-другому (например, free ничего не делает, когда передается нулевой указатель).

Notes

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

Для функции, которая обращается к объектам через указатели, можно указать, что эти указатели не являются псевдонимами. Смотрите ограничения для деталей.

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

Указатели на символы часто используются для представления строк . Чтобы представить действительную строку байтов, указатель должен указывать на символ, который является элементом массива символов, и должен быть символ со значением ноль при некотором индексе, большем или равном индексу элемента, на который ссылается указатель.

C Pointer to Pointer, Pointer to Functions, Array of Pointers Explained with Examples

In C programming language, the concept of pointers is the most powerful concept that makes C stand apart from other programming languages. In the part-I of this series we discussed the fundamental concepts around C pointers.

In this article, we will try to develop understanding of some of the relatively complex concepts. The following are explained in this article with examples:

  1. Constant pointer and pointer to constant.
  2. Pointer to pointer with an example
  3. Array of pointers with an example
  4. Pointer to functions with an example

1. C Constant Pointer and Pointer to Constant

As a developer, you should understand the difference between constant pointer and pointer to constant.

C Constant pointer

A pointer is said to be constant pointer when the address its pointing to cannot be changed.

Lets take an example :

In the above example we defined two characters (‘ch’ and ‘c’) and a character pointer ‘ptr’. First, the pointer ‘ptr’ contained the address of ‘ch’ and in the next line it contained the address of ‘c’. In other words, we can say that Initially ‘ptr’ pointed to ‘ch’ and then it pointed to ‘c’.

But in case of a constant pointer, once a pointer holds an address, it cannot change it. This means a constant pointer, if already pointing to an address, cannot point to a new address.

If we see the example above, then if ‘ptr’ would have been a constant pointer, then the third line would have not been valid.

A constant pointer is declared as :

When the code above is compiled, compiler gives the following error :

So we see that, as expected, compiler throws an error since we tried to change the address held by constant pointer.

Now, we should be clear with this concept. Lets move on.

C Pointer to Constant

This concept is easy to understand as the name simplifies the concept. Yes, as the name itself suggests, this type of pointer cannot change the value at the address pointed by it.

Lets understand this through an example :

In the above example, we used a character pointer ‘ptr’ that points to character ‘ch’. In the last line, we change the value at address pointer by ‘ptr’. But if this would have been a pointer to a constant, then the last line would have been invalid because a pointer to a constant cannot change the value at the address its pointing to.

A pointer to a constant is declared as :

When the above code was compiled, compiler gave the following error :

So now we know the reason behind the error above ie we cannot change the value pointed to by a constant pointer.

2. C Pointer to Pointer

Till now we have used or learned pointer to a data type like character, integer etc. But in this section we will learn about pointers pointing to pointers.

As the definition of pointer says that its a special variable that can store the address of an other variable. Then the other variable can very well be a pointer. This means that its perfectly legal for a pointer to be pointing to another pointer.

Lets suppose we have a pointer ‘p1’ that points to yet another pointer ‘p2’ that points to a character ‘ch’. In memory, the three variables can be visualized as :

So we can see that in memory, pointer p1 holds the address of pointer p2. Pointer p2 holds the address of character ‘ch’.

So ‘p2’ is pointer to character ‘ch’, while ‘p1’ is pointer to ‘p2’ or we can also say that ‘p2’ is a pointer to pointer to character ‘ch’.

Now, in code ‘p2’ can be declared as :

But ‘p1’ is declared as :

So we see that ‘p1’ is a double pointer (ie pointer to a pointer to a character) and hence the two *s in declaration.

  • ‘p1’ is the address of ‘p2’ ie 5000
  • ‘*p1’ is the value held by ‘p2’ ie 8000
  • ‘**p1’ is the value at 8000 ie ‘c’

I think that should pretty much clear the concept, lets take a small example :

Here is the output :

3. C Array of Pointers

Just like array of integers or characters, there can be array of pointers too.

An array of pointers can be declared as :

The above line declares an array of three character pointers.

Lets take a working example :

In the above code, we took three pointers pointing to three strings. Then we declared an array that can contain three pointers. We assigned the pointers ‘p1’, ‘p2’ and ‘p3’ to the 0,1 and 2 index of array. Let’s see the output :

So we see that array now holds the address of strings.

4. C Function Pointers

Just like pointer to characters, integers etc, we can have pointers to functions.

A function pointer can be declared as :

The above line declares a function pointer ‘fptr’ that can point to a function whose return type is ‘int’ and takes two integers as arguments.

Lets take a working example :

In the above example, we defined a function ‘func’ that takes two integers as inputs and returns an integer. In the main() function, we declare a function pointer ‘fptr’ and then assign value to it. Note that, name of the function can be treated as starting address of the function so we can assign the address of function to function pointer using function’s name. Lets see the output :

So from the output we see that calling the function through function pointer produces the same output as calling the function from its name.

To conclude, in this article we touched some of the advanced concepts related to pointers. There can be some interesting problems related to pointers, which we might cover in some future article.

Pointer declaration

Declares a variable of a pointer or pointer-to-member type.

Contents

[edit] Syntax

A pointer declaration is any simple declaration whose declarator has the form

* attr (optional) cv (optional) declarator (1)
nested-name-specifier * attr (optional) cv (optional) declarator (2)
nested-name-specifier a sequence of names and scope resolution operators ::
attr (since C++11) a list of attributes
cv const/volatile qualification which apply to the pointer that is being declared (not to the pointed-to type, whose qualifications are part of decl-specifier-seq )
declarator any declarator other than a reference declarator (there are no pointers to references). It can be another pointer declarator (pointer to pointers are allowed)

There are no pointers to references and there are no pointers to bit fields. Typically, mentions of «pointers» without elaboration do not include pointers to (non-static) members.

[edit] Pointers

Every value of pointer type is one of the following:

  • a pointer to an object or function (in which case the pointer is said to point to the object or function), or
  • a pointer past the end of an object, or
  • the null pointer value for that type, or
  • an invalid pointer value.

A pointer that points to an object represents the address of the first byte in memory occupied by the object. A pointer past the end of an object represents the address of the first byte in memory after the end of the storage occupied by the object.

Note that two pointers that represent the same address may nonetheless have different values.

Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior. Some implementations might define that copying an invalid pointer value causes a system-generated runtime fault.

[edit] Pointers to objects

A pointer to object can be initialized with the return value of the address-of operator applied to any expression of object type, including another pointer type:

Pointers may appear as operands to the built-in indirection operator (unary operator * ), which returns the lvalue expression identifying the pointed-to object:

Pointers to class objects may also appear as the left-hand operands of the member access operators operator-> and operator->* .

Because of the array-to-pointer implicit conversion, pointer to the first element of an array can be initialized with an expression of array type:

Because of the derived-to-base implicit conversion for pointers, pointer to a base class can be initialized with the address of a derived class:

If Derived is polymorphic, such pointer may be used to make virtual function calls.

Certain addition, subtraction, increment, and decrement operators are defined for pointers to elements of arrays: such pointers satisfy the LegacyRandomAccessIterator requirements and allow the C++ library algorithms to work with raw arrays.

Comparison operators are defined for pointers to objects in some situations: two pointers that represent the same address compare equal, two null pointer values compare equal, pointers to elements of the same array compare the same as the array indexes of those elements, and pointers to non-static data members with the same member access compare in order of declaration of those members.

Many implementations also provide strict total ordering of pointers of random origin, e.g. if they are implemented as addresses within continuous virtual address space. Those implementations that do not (e.g. where not all bits of the pointer are part of a memory address and have to be ignored for comparison, or an additional calculation is required or otherwise pointer and integer is not a 1 to 1 relationship), provide a specialization of std::less for pointers that has that guarantee. This makes it possible to use all pointers of random origin as keys in standard associative containers such as std::set or std::map .

[edit] Pointers to void

Pointer to object of any type can be implicitly converted to pointer to void (optionally cv-qualified); the pointer value is unchanged. The reverse conversion, which requires static_cast or explicit cast, yields the original pointer value:

If the original pointer is pointing to a base class subobject within an object of some polymorphic type, dynamic_cast may be used to obtain a void * that is pointing at the complete object of the most derived type.

Pointers to void have the same size, representation and alignment as pointers to char .

Pointers to void are used to pass objects of unknown type, which is common in C interfaces: std::malloc returns void * , std::qsort expects a user-provided callback that accepts two const void * arguments. pthread_create expects a user-provided callback that accepts and returns void * . In all cases, it is the caller’s responsibility to cast the pointer to the correct type before use.

[edit] Pointers to functions

A pointer to function can be initialized with an address of a non-member function or a static member function. Because of the function-to-pointer implicit conversion, the address-of operator is optional:

Unlike functions or references to functions, pointers to functions are objects and thus can be stored in arrays, copied, assigned, etc.

Note: declarations involving pointers to functions can often be simplified with type aliases:

A pointer to function can be used as the left-hand operand of the function call operator, this invokes the pointed-to function:

Dereferencing a function pointer yields the lvalue identifying the pointed-to function:

A pointer to function may be initialized from an overload set which may include functions, function template specializations, and function templates, if only one overload matches the type of the pointer (see address of an overloaded function for more detail):

Equality comparison operators are defined for pointers to functions (they compare equal if pointing to the same function).

[edit] Pointers to members

[edit] Pointers to data members

A pointer to non-static member object m which is a member of class C can be initialized with the expression & C :: m exactly. Expressions such as & ( C :: m ) or & m inside C ‘s member function do not form pointers to members.

Such pointer may be used as the right-hand operand of the pointer-to-member access operators operator. * and operator — > * :

Pointer to data member of an accessible unambiguous non-virtual base class can be implicitly converted to pointer to the same data member of a derived class:

Conversion in the opposite direction, from a pointer to data member of a derived class to a pointer to data member of an unambiguous non-virtual base class, is allowed with static_cast and explicit cast, even if the base class does not have that member (but the most-derived class does, when the pointer is used for access):

The pointed-to type of a pointer-to-member may be a pointer-to-member itself: pointers to members can be multilevel, and can be cv-qualified differently at every level. Mixed multi-level combinations of pointers and pointers-to-members are also allowed:

[edit] Pointers to member functions

A pointer to non-static member function f which is a member of class C can be initialized with the expression & C :: f exactly. Expressions such as & ( C :: f ) or & f inside C ‘s member function do not form pointers to member functions.

Such pointer may be used as the right-hand operand of the pointer-to-member access operators operator. * and operator — > * . The resulting expression can be used only as the left-hand operand of a function-call operator:

Pointer to member function of a base class can be implicitly converted to pointer to the same member function of a derived class:

Conversion in the opposite direction, from a pointer to member function of a derived class to a pointer to member function of an unambiguous non-virtual base class, is allowed with static_cast and explicit cast, even if the base class does not have that member function (but the most-derived class does, when the pointer is used for access):

Pointers to member functions may be used as callbacks or as function objects, often after applying std::mem_fn or std::bind :

[edit] Null pointers

Pointers of every type have a special value known as null pointer value of that type. A pointer whose value is null does not point to an object or a function (the behavior of dereferencing a null pointer is undefined), and compares equal to all pointers of the same type whose value is also null.

To initialize a pointer to null or to assign the null value to an existing pointer, the null pointer literal nullptr , the null pointer constant NULL , or the implicit conversion from the integer literal with value ​ 0 ​ may be used.

Zero- and value-initialization also initialize pointers to their null values.

Null pointers can be used to indicate the absence of an object (e.g. function::target()), or as other error condition indicators (e.g. dynamic_cast). In general, a function that receives a pointer argument almost always needs to check if the value is null and handle that case differently (for example, the delete expression does nothing when a null pointer is passed).

[edit] Constness

  • If cv appears before * in the pointer declaration, it is part of decl-specifier-seq and applies to the pointed-to object.
  • If cv appears after * in the pointer declaration, it is part of declarator and applies to the pointer that’s being declared.

In general, implicit conversion from one multi-level pointer to another follows the rules described in qualification conversions and in pointer comparison operators.

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

Читать:
Как в аутлуке отправить письмо нескольким адресатам

Похожие статьи