Вопрос: Что означает указатель на постоянную функцию?


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

Мои коллеги и я обсуждали использование «const» с указателями, и возник вопрос о том, как использовать const с указателями функций.

Вот несколько вопросов:

  1. В чем смысл указателя на постоянную функцию по сравнению с указатель на непостоянную функцию?
  2. Может ли функция быть const?
  3. Может ли функция быть непостоянной (изменчивой)?
  4. Каков правильный (безопасный) синтаксис для передачи указателя функции?

Редактировать 1: Синтаксис указателя функции

typedef void (*Function_Pointer)(void); // Pointer to void function returning void.

void function_a(Function_Pointer p_func); // Example 1.
void function_b(const Function_Pointer p_func); // Example 2.
void function_c(Function_Pointer const p_func); // Example 3.
void function_d(const Function_Pointer const p_func); // Example 4.

Вышеприведенные объявления являются примерами обработки указателя функции как указателя на собственный тип.

Указатель данных, переменной или памяти позволяет использовать приведенные выше комбинации.
Таким образом, вопросы таковы: может ли указатель функции иметь одни и те же комбинации и что подразумевается под указателем на функцию const (например, пример 2)?


22


источник


Ответы:


В C нет такой функции, как функция const или иначе, поэтому указатель на функцию const не имеет смысла (не должен компилироваться, хотя я не проверял какой-либо конкретный компилятор).

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

// normal pointer to function
int (*func)(int);

// pointer to const function -- not allowed
int (const *func)(int);

// const pointer to function. Allowed, must be initialized.          
int (*const func)(int) = some_func;

// Bonus: pointer to function returning pointer to const
void const *(*func)(int);

// triple bonus: const pointer to function returning pointer to const.
void const *(*const func)(int) = func.

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


40



Согласно спецификации C ( C99 , раздел 6.7.3):

Свойства, связанные с квалифицированными типами, имеют смысл только для   выражения, которые являются lvalues.

Когда спецификация говорит «квалифицированные типы», это означает, что const, restrict, или volatile ключевое слово. Функции Snice не являются lvalues, const ключевое слово в функции не имеет смысла. Возможно, вы ищете какое-то расширение для компилятора. Некоторые компиляторы будут вызывать ошибку, если вы попытаетесь объявить функцию как const,

Вы уверены, что ищете указатель на постоянную функцию, а не постоянный указатель на функцию (то есть, это указатель  это const, а не функция)?

Что касается № 4: см. это руководство  для полезного обзора создания, передачи и использования указателей функций.


6



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

В C ++ методы могут быть const, Если метод const, это означает, что после вызова этого метода объект, содержащий этот метод, будет находиться в том же состоянии, что и до того, как вы вызвали этот метод (ни одна из переменных экземпляра [1] не была изменена). Таким образом, вы можете указать на метод const и метод non-const, и эти методы разные.

Вы можете принять указатель на функцию в списке аргументов как retType (*variableName)(arguments),

[1] Если они не mutable,


2



В C функции Можно  быть const если вы в мире GCC! Функции могут быть объявлены const посредством использования атрибутов, связанных с объявлениями функций и другими символами. Он в основном используется для предоставления информации компилятору о том, что делает функция, даже несмотря на то, что ее тело недоступно, чтобы компилятор мог делать с ним какие-то оптимизации.

Постоянная функция обычно определяется в терминах pure функция.

Чистая функция - это функция с практически отсутствием побочного эффекта. Эта   означает, что чистые функции возвращают значение, которое рассчитывается на основе   заданные параметры и глобальную память, но не могут влиять на значение любого   другая глобальная переменная. Чистые функции не могут разумно не иметь возврата   тип (т. е. имеет тип возврата void).

И теперь мы можем определить, что такое функция const,

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

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

Читать полностью проницательная статья  Вот.

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


2



1. В чем смысл указателя на постоянную функцию по сравнению с указателем на непостоянную функцию?

Нет никакой разницы между константой и несостоянием: сама функция не модифицируется

Примечание. В C ++, если функция является функцией-членом класса, const означает, что состояние объекта внутри этой функции не может быть изменено (переменные-члены, назначенные, вызываемые не-константные функции memeber). В этом случае ключевое слово const является частью сигнатуры функции-члена и поэтому имеет значение в терминах указателя.

2. Может ли функция быть const?

См. Выше.

3. Может ли функция быть непостоянной (изменчивой)?

См. Выше

4. Каков правильный (безопасный) синтаксис для передачи указателя функции?

Все указатели на свободные функции могут быть переведены на любой другой указатель на свободную функцию (т. Е. Их размер одинаковый). Таким образом, вы можете определить тип для (гипотетической) функции: void f(); и конвертировать все указатели на функции в этот тип для хранения. Заметка  что вы не должны вызывать функцию через этот общий тип: вам нужно отдать его bact на его исходный тип указателя на функцию, иначе вы получите неопределенное поведение (и, скорее всего, сбой)

Для C ++: указатели на функции-члены не гарантируются преобразованием в указатели на свободные функции


0



1. Синтаксически нет места для размещения 'const' для создания функции содержание  постоянная.

Вы столкнетесь с ошибкой «функция не является l-значением», независимо от того, имеет ли она константу или нет.

typedef void (* FUNC)(void);
FUNC pFunc;
pFunc = 0;     // OK
*pFunc = 0;    // error:  Cannot assign to a function (a function is not an l-value)

typedef void (* const FUNC)(void);
FUNC pFunc;
pFunc = 0;     // error  (const)
*pFunc = 0;    // error:  Cannot assign to a function (a function is not an l-value)

typedef void (const * FUNC)(void);   // error:  <cv-qualifier>  (lol?)

2 и 3. Указатели функций - да. Содержимое функции не похоже.

4. Я не думаю, что есть способ сделать передачу указателя функции более безопасной. Со всеми константами в мире единственное, что вы можете защитить, это то, что «SetCallback» не может изменить собственную локальную копию этого параметра.

typedef void (* const FUNC)(void);
void SetCallback(const FUNC const pCallback)
{
  FUNC pTemp = pCallback;   // OK  (even though pTemp is not const!!)
  pCallback = 0;            // error  (const)
}

0