指针可以声明为指向可变(非常量)数据或指向常量数据的指针 可以将指针定义为指向函数。
我的同事和我正在讨论使用带有指针的“const”问题,并且出现了关于const
与函数指针一起使用的问题。
以下是一些问题:
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)是什么意思?
答案 0 :(得分:46)
在C中,没有函数是const
或其他函数,所以指向const函数的指针是没有意义的(不应该编译,尽管我没有检查过任何特定的编译器)。 / p>
请注意,尽管它有所不同,但您可以拥有一个指向函数的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.
只要将指向函数的指针作为参数传递,它就非常简单了。您通常只想将指针传递给正确的类型。但是,指向任何类型函数的指针都可以转换为指向其他类型函数的指针,然后返回其原始类型,并保留原始值。
答案 1 :(得分:6)
根据C规范(C99,第6.7.3节):
与限定类型关联的属性仅对其有意义 表达式是左值。
当规范说明"限定类型"时,它表示使用const
,restrict
或volatile
关键字定义的内容。 Snice函数不是左值,函数上的const
关键字没有意义。您可能正在查看某种特定于编译器的扩展。如果您尝试将函数声明为const
,则某些编译器会抛出错误。
你确定你正在查看指向常量函数的指针,而不是指向函数的常量指针(也就是说,它是指针' s const
,而不是功能)?
关于#4:有关创建,传递和使用函数指针的有用概述,请参阅this guide。
答案 2 :(得分:2)
在C下,没有const
功能。 const
是一个类型限定符,因此只能用于限定类型,而不是函数。也许你的意思是指向函数的const指针或函数的非const指针?
在C ++中,方法可以是const
。如果方法是const
,则意味着在调用该方法之后,包含该方法的对象将处于与调用该方法之前相同的状态(没有修改任何实例变量[1])。因此,您可以指向const方法和非const方法,这些方法是不同的。
您可以接受参数列表中的函数指针retType (*variableName)(arguments)
。
[1]除非它们是mutable
。
答案 3 :(得分:2)
在C中,如果你在GCC的世界,函数可以 const
!可以通过使用附加到函数声明和其他符号的属性来声明函数const
。它基本上用于向编译器提供有关函数功能的信息,即使它的主体不可用,以便编译器可以对它进行某种优化。
常量函数通常根据pure
函数定义。
纯函数是一种基本没有副作用的函数。这个 表示纯函数返回基于的计算值 给定参数和全局内存,但不能影响任何值 其他全局变量。纯粹的功能不能合理地缺乏回报 type(即具有void返回类型)。
现在我们可以定义什么是const函数,
一个不访问全局内存但只访问全局内存的纯函数 参数,称为常数函数。这是因为 与全局记忆状态无关的功能将永远存在 给定相同参数时返回相同的值。返回值 因此,它直接而且完全来自于它的价值 给出的参数。
这里const
并不意味着函数可变性。但它是一种不触及全局记忆的功能。您可以为这些函数指定常规指针。无论如何,代码区域一般(忘记自修改代码一段时间)是RO,你不能通过普通指针修改它。
在此处阅读完整的insightful article。
因此,当谈到 GCC常量函数时,我们讨论的是优化而不是函数可变性。
答案 4 :(得分:0)
1.指向常量函数的指针与指向非常量函数的指针的含义是什么?
const和非const之间没有区别:函数本身不可修改
注意:在C ++中,如果函数是类的成员函数,则const表示不能更改此函数中对象的状态(调用成员变量,调用非const memeber函数)。在这种情况下,const关键字是成员函数签名的一部分,因此在指针方面有所不同。
2.一个函数可以是const吗?
见上文。
3.一个函数可以是非const(可变)吗?
见上文
4.传递函数指针的正确(安全)语法是什么?
所有指向自由函数的指针都可以转换为任何其他指向自由函数的指针(即它们的大小相同)。因此,您可以为(假设的)函数定义类型:void f();
并将所有函数指针转换为此类型以进行存储。 注意你不应该通过这种常见的类型来调用函数:你需要将它转换成它的原始指针到函数类型,否则你会得到未定义的行为(并且很可能会崩溃)
对于C ++:不保证指向成员函数的指针可转换为指向自由函数的指针
答案 5 :(得分:0)
1。 在语法上无处放置'const'来使函数的内容不变。
无论你是不是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&amp; 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)
}