32

指针可以声明为指向可变(非常量)数据或指向常量数据的指针。
指针可以定义为指向函数。

我和我的同事正在讨论将“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)?

4

6 回答 6

59

在 C 中,没有函数存在const或其他情况,因此指向 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.

至于将指向函数的指针作为参数传递,这非常简单。您通常只想传递一个指向正确类型的指针。但是,指向任何类型函数的指针都可以转换为指向其他类型函数的指针,然后变回其原始类型,并保留原始值。

于 2012-04-13T17:59:46.907 回答
6

根据 C 规范(C99,第 6.7.3 节):

与限定类型关联的属性仅对作为左值的表达式有意义。

当规范说“限定类型”时,它表示用 , 或 关键字定义constrestrict东西volatile。Snice 函数不是左值,函数上的const关键字没有意义。您可能正在查看某种特定于编译器的扩展。如果您尝试将函数声明为const.

您确定您正在查看指向常量函数的指针而不是指向函数的常量指针(也就是说,它是指针const而不是函数)?

关于#4:有关创建、传递和使用函数指针的有用概述,请参阅本指南。

于 2012-04-13T17:54:08.903 回答
2

在 C 中,没有const函数这样的东西。 const是一个类型限定符,因此只能用于限定一个类型,而不是一个函数。也许您的意思是指向函数的 const 指针或指向函数的非常量指针?

在 C++ 中,方法可以是const. 如果一个方法是const,这意味着在您调用该方法之后,包含该方法的对象将处于与您调用该方法之前相同的状态(没有任何实例变量[1]被修改)。因此,您可以指向一个 const 方法和一个非常量方法,并且这些方法是不同的。

您可以将参数列表中的函数指针作为retType (*variableName)(arguments).

[1] 除非他们是mutable.

于 2012-04-13T17:48:30.340 回答
2

如果您在 GCC 的世界中,那么在 C 中,函数可以是!const可以const通过使用附加到函数和其他符号声明的属性来声明函数。它基本上用于向编译器提供有关函数作用的信息,即使它的主体不可用,以便编译器可以对其进行某种优化。

常数函数通常用函数来定义pure

纯函数是基本上没有副作用的函数。这意味着纯函数返回一个基于给定参数和全局内存计算的值,但不会影响任何其他全局变量的值。纯函数不能合理地缺少返回类型(即具有 void 返回类型)。

现在我们可以定义什么是 const 函数,

不访问全局内存而只访问其参数的纯函数称为常量函数。这是因为与全局内存状态无关的函数在给定相同参数时将始终返回相同的值。因此,返回值直接且排他地从给定参数的值中导出。

这里const并不暗示任何关于函数可变性的事情。但它是一个不涉及全局内存的功能。您可以将普通指针分配给此类函数。无论如何,代码区域通常(暂时忘记自我修改代码)是 RO,您不能通过普通指针对其进行修改。

在此处阅读完整的有见地的文章

因此,当谈到GCC 常量函数时,我们谈论的是优化而不是函数可变性。

于 2012-04-13T18:24:47.113 回答
0

1.指向常量函数的指针与指向非常量函数的指针是什么意思?

const 和 non-const 没有区别:函数本身是不可修改的

注意:在 C++ 中,如果函数是类的成员函数,则 const 表示该函数内对象的状态不能更改(分配给成员变量,调用非 const 成员函数)。在这种情况下, const 关键字是成员函数签名的一部分,因此在指针方面有所不同。

2.函数可以是const吗?

往上看。

3.函数可以是非常量(可变)吗?

往上看

4.传递函数指针的正确(安全)语法是什么?

所有指向自由函数的指针都可以转换为任何其他指向自由函数的指针(即它们的大小相同)。因此,您可以为(假设的)函数定义一个类型:void f();并将所有函数指针转换为该类型以进行存储。 请注意,您不应该通过这种通用类型调用该函数:您需要将其强制转换为原来的指向函数的指针类型,否则您会得到未定义的行为(并且很可能会崩溃)

对于 C++:不保证指向成员函数的指针可转换为指向自由函数的指针

于 2012-04-13T18:05:56.360 回答
0

1. 在语法上没有地方可以放置“const”来使函数的内容保持不变。

无论您是否有 const,您都会遇到“函数不是左值”错误。

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)
}
于 2012-04-13T18:15:33.803 回答