带有 typedef 函数指针的 const 限定符
const-qualifier with typedef-ed function pointer
关于 typedef 函数指针在函数参数中被 const 限定,C 标准有什么规定?例如,假设我有以下类型
typedef int (*Operation)(int a, int b);
我有一堆操作需要两个整数,执行操作,然后 returns 一个整数。然后我有一个执行实际函数指针调用的函数。
int doOpOnce(const Operation op, int a, int b)
{
return op(a, b);
}
我想保证函数指针在 doOpOnce
调用期间不会改变,我还想向 doOpOnce
的用户证明它实际上会调用提供给它的函数。这有效吗?有什么区别吗:
int doOpOnce(const Operation op, int a, int b)
int doOpOnce(Operation const op, int a, int b)
最后,举个例子。它是用带有标志 -std=c99 -Wall -Wextra -pedantic
的 gcc 4.9.2 编译的,当我尝试更改我的 const 函数指针时它会正确出错。
#include <stdio.h>
typedef int (*Operation)(int a, int b);
int opAdd(int a, int b)
{
return a + b;
}
int opSub(int a, int b)
{
return a - b;
}
int doOpOnce(const Operation op, int a, int b)
{
op = opSub; // error: assignment of read-only parameter 'op'
return op(a, b);
}
int main()
{
printf("%d\n", doOpOnce(opAdd, 10, 20));
return 0;
}
我不想将 const 限定符添加到 Operation
typedef,因为我有其他函数可以修改 Operation
指针。我只是想要在某些情况下更强的打字能力。
让外界(.h)看到int doOpOnce(Operation op, int a, int b);
和你的.c文件实现int doOpOnce(Operation const op, int a, int b) {
所以"to guarantee that the function pointer doesn't change during the doOpOnce"
"I also want to document to users of doOpOnce that it will actually call the function given to it. " 属于代码文档。
int doOpOnce(Operation const op, int a, int b);
的函数声明签名不足以保证 "it will actually call the function given to it"。
如果参数类型是 Operation,调用者将指针的副本传递给函数,因此函数实际上无法更改指针指向调用者的位置。在此处添加 const 关键字只是实现中的一种防御技术,可防止您重新分配本地副本。从这个意义上说,您甚至可能不需要 const 限定符来向您的图书馆的客户发出任何信号。
针对你的另一个问题,const的两个位置意义相同,你可以随意选择一个。
对于函数 doOpOnce
的用户来说,指向函数的指针是否使用 const
限定符声明并不重要,因为该函数处理用户提供的原始指针的副本作为论点。
对于函数的使用者这两个函数声明
int doOpOnce(const Operation op, int a, int b);
和
int doOpOnce( Operation op, int a, int b);
声明同一个函数。您可以在程序中包含这两个声明。
只有在函数定义中,您才能将此指针作为函数 的局部变量更改为任何参数。
.
关于 typedef 函数指针在函数参数中被 const 限定,C 标准有什么规定?例如,假设我有以下类型
typedef int (*Operation)(int a, int b);
我有一堆操作需要两个整数,执行操作,然后 returns 一个整数。然后我有一个执行实际函数指针调用的函数。
int doOpOnce(const Operation op, int a, int b)
{
return op(a, b);
}
我想保证函数指针在 doOpOnce
调用期间不会改变,我还想向 doOpOnce
的用户证明它实际上会调用提供给它的函数。这有效吗?有什么区别吗:
int doOpOnce(const Operation op, int a, int b)
int doOpOnce(Operation const op, int a, int b)
最后,举个例子。它是用带有标志 -std=c99 -Wall -Wextra -pedantic
的 gcc 4.9.2 编译的,当我尝试更改我的 const 函数指针时它会正确出错。
#include <stdio.h>
typedef int (*Operation)(int a, int b);
int opAdd(int a, int b)
{
return a + b;
}
int opSub(int a, int b)
{
return a - b;
}
int doOpOnce(const Operation op, int a, int b)
{
op = opSub; // error: assignment of read-only parameter 'op'
return op(a, b);
}
int main()
{
printf("%d\n", doOpOnce(opAdd, 10, 20));
return 0;
}
我不想将 const 限定符添加到 Operation
typedef,因为我有其他函数可以修改 Operation
指针。我只是想要在某些情况下更强的打字能力。
让外界(.h)看到int doOpOnce(Operation op, int a, int b);
和你的.c文件实现int doOpOnce(Operation const op, int a, int b) {
所以"to guarantee that the function pointer doesn't change during the doOpOnce"
"I also want to document to users of doOpOnce that it will actually call the function given to it. " 属于代码文档。
int doOpOnce(Operation const op, int a, int b);
的函数声明签名不足以保证 "it will actually call the function given to it"。
如果参数类型是 Operation,调用者将指针的副本传递给函数,因此函数实际上无法更改指针指向调用者的位置。在此处添加 const 关键字只是实现中的一种防御技术,可防止您重新分配本地副本。从这个意义上说,您甚至可能不需要 const 限定符来向您的图书馆的客户发出任何信号。
针对你的另一个问题,const的两个位置意义相同,你可以随意选择一个。
对于函数 doOpOnce
的用户来说,指向函数的指针是否使用 const
限定符声明并不重要,因为该函数处理用户提供的原始指针的副本作为论点。
对于函数的使用者这两个函数声明
int doOpOnce(const Operation op, int a, int b);
和
int doOpOnce( Operation op, int a, int b);
声明同一个函数。您可以在程序中包含这两个声明。
只有在函数定义中,您才能将此指针作为函数 的局部变量更改为任何参数。 .