(*)在普通C中意味着什么?

时间:2013-04-10 16:45:54

标签: c pointers

我无法在以下语句中得到“(*)”表达式的含义:

#define PySpam_System \
 (*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])

其中

#define PySpam_System_NUM 0
#define PySpam_System_RETURN int
#define PySpam_System_PROTO (const char *command)

(摘自http://docs.python.org/2/extending/extending.html)。这意味着什么? (请原谅我一个愚蠢的问题)。类似于函数指针,但语法非常混乱。

更新:感谢Shahbaz和Jonathan,事情变得越来越明显,但我仍然无法获得两个细微差别:

  1. 为什么const char *command,而不仅仅是const char *。我认为在函数指针类型声明和类型转换中应该省略参数的名称?所以一定不能省略,而是可以吗?
  2. 为什么(*(int (*)(const char *command)),而不只是(int (*)(const char *command)?外部(* [此处其他所有内容] )的目的是什么?它是函数指针的可选解引用,对吧?

2 个答案:

答案 0 :(得分:7)

PySpam_System_RETURN (*)PySpam_System_PROTO

扩展为:

int (*)(const char *command)

这是一个函数指针类型。所以基本上如下:

(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])

转换为:

(*(int (*)(const char *command)) PySpam_API[0])

正在调用PySpam_API[0]的值,好像它是一个带有const char*参数和int返回值的函数(强制转换为函数指针)。请注意,这仍然缺少参数,因此无论谁使用宏都应该给它参数,例如:

PySpam_System("some string");

在您的更新中:

  1. 参数名称是可选的。他们本来可以写const char *。我相信这个名字是为了清晰起见而写的。现在,我没有看其他任何地方,我明白该功能需要一个命令,所以我会说这很有帮助。
  2. 再次,你是对的。最初的*取消引用函数指针。在C中,这是非常可选的。把它放得更加对称,因为你正在取消引用一个指针,但是由于没有取消引用一个函数指针没有意义,如果你不解引它就没有任何区别,C会做唯一合理的事情为了你。事实上,即使你把******而不只是一个,它仍然有用。

答案 1 :(得分:5)

使用预处理器展开PySpam_System,您会看到:

(*(int (*)(const char *command)) PySpam_API[0])

表达式(或多或少)是对'返回int的函数的指针并且采用类型const char *'的一个参数的强制转换。它必须跟随("something"),通过指向函数的指针将整个转换为函数调用。因此,在代码中,您可能会看到:

PySpam_System("abc");

,编译器会看到:

(*(int (*)(const char *command)) PySpam_API[0])("abc");

,这是对存储在索引位置0的数组PySpam_API中的函数的调用。显然,参数可能不是简单的字符串文字,但是简单的字符串文字是代表{{1} }。


问题更新

  

为什么const char *,而不只是const char *command。我认为在函数指针类型声明和类型转换中应该省略参数的名称?所以一定不能省略,而是可以吗?

参数的名称(例如示例中的const char *)在原型声明中是可选的。也没有规则声明原型声明中的名称必须与函数定义中的名称匹配。遗憾的是,如果你正在编写一个符合接口的函数但是函数的特定实现不需要参数,那么C还没有采用C ++约定,即函数定义中的名称是可选的。也就是说,在C ++中,你可以写:

command

函数typedef int (*interface)(const char *cmd, int arg1, int arg2); static int implementation(const char *cmd, int arg1, int) // C++, not C { return some_other_function(cmd, arg1, 23, 19); } 符合implementation类型,但不使用interface参数,但编译器不会抱怨未使用的参数。 C不允许这样的方便,所以即使你完全清楚它未被使用,你也会被告知'未使用的参数'。我相信这个特定问题有特定于编译器的方法。

  

为什么arg2,而不只是(*(int (*)(const char *command))?外(int (*)(const char *command)的目的是什么?它是函数指针的可选解引用,对吧?

右。

请注意,有两种方法可以通过指向函数的指针调用函数,大致是“旧”和“新”(其中new表示“由C89标准引入和祝福”,所以它并不完全是'新的' “)。

需要旧的表示法(给出或采取当时不可用的原型):

(*[everything else here])
带有括号的

和函数指针周围的#include <math.h> double (*func)(double) = sin; double x = (*func)(1.0); 。这个想法是,如果你有一个指向函数的指针,你需要取消引用它来调用该函数。更现代的符号表明函数的名称成为函数的指针(例如在赋值中),因此您实际上不需要*符号。因此,较新的风格是:

(*func)

由于我在旧风格必修时学会了C语言,我仍然更喜欢略显冗长但完全明确的符号。 #include <math.h> double (*func)(double) = sin; double x = func(1.0); 宏中的代码也使用较旧的表示法。

您还可以使用功能指针玩各种愚蠢的游戏,添加额外的PySpam_System并使用*,所有这些都是不必要的。

&

只有double (*funca)(double) = &sin; double (*func0)(double) = sin; double (*func1)(double) = *sin; double (*func2)(double) = **sin; double (*func3)(double) = ***sin; 声明是明智的;其余的是混淆C.