C - 这个函数指针声明是什么意思?

9

我正在分析一些多线程代码。在初始化函数中,有这样一段代码:

for(i=0;i<MAX_STREAMS;i++){
    cmdStreamTaskPtr[i] = NULL;
}

我能理解该语法,但我的问题在于 cmdStreamTaskPtr 的声明。它是以以下方式定义的:cmdData_t 是一个typedef struct,而 MAX_STREAMS 则为5。
static cmdData_t *(*cmdStreamTaskPtr[MAX_STREAMS])(void) = {[0 ... MAX_STREAMS-1] = NULL};

我不知道这行是什么意思。它是一个带有默认值的变量吗?

2
你可能会发现这个网站很有用... - Eugene Sh.
我们是否有这种问题的规范重复目标? - HolyBlackCat
@EugeneSh。我实际上尝试过了,那个网站似乎无法处理这个特定的声明。即使我删除了语句的初始化部分,它仍然报告语法错误。 - David Z
你可以用一个数字替换宏,用一些标准类型替换类型。这些东西它不知道。 - Eugene Sh.
2个回答

25

cmdStreamTaskPtr是一个数组:

cmdStreamTaskPtr[MAX_STREAMS]

指针:

*cmdStreamTaskPtr[MAX_STREAMS]

对于不接受任何参数的函数:

(*cmdStreamTaskPtr[MAX_STREAMS])(void)

并返回一个cmdData_t *

cmdData_t *(*cmdStreamTaskPtr[MAX_STREAMS])(void)

而且是静态的:

static cmdData_t *(*cmdStreamTaskPtr[MAX_STREAMS])(void)

数组的所有元素都使用NULL进行初始化:

static cmdData_t *(*cmdStreamTaskPtr[MAX_STREAMS])(void) = {[0 ... MAX_STREAMS-1] = NULL};

注意,初始化语法[0 ... MAX_STREAMS-1]不是标准的C语言,而是GCC支持的扩展功能。在这种情况下,这也是多余的,因为数组已被声明为static,这意味着它具有静态存储期限,因此如果没有明确初始化,其元素会隐式地初始化为NULL
使用函数指针可以通过typedef更清晰地表达。在这种情况下,我们可以创建以下 typedef:
typedef cmdData_t *(*fp)(void);

这使得fp成为一个指向不带参数并返回cmdData_t *的函数指针。数组定义可以更改为:

static fp cmdStreamTaskPtr[MAX_STREAMS];

现在应该更清楚了,cmdStreamTaskPtrfp数组,其中fp是之前定义的函数指针。


[0 ... MAX_STREAMS-1] = NULL 是编译器的扩展吗?我从未见过这种语法。编辑:是的 - Kevin
7
请注意,初始化程序是100%多余的。变量是static,因此默认情况下将进行零初始化。 - melpomene
你介意写一个非常简单的代码,类似于通过调用声明的定义作为函数来声明吗?我想出于完全教育目的来检查它,拜托了. - Soner from The Ottoman Empire
1
@snr 这样的函数可以像这样调用:cmdData_t *var = cmdStreamTaskPtr[0](); - dbush
1
现在,使用typedef来完成 - 这只是说明为什么在这里使用typedef很有用的一个例子。;-) - Andrew Henle
显示剩余2条评论

-2

cmdStreamTaskPtr 是一个指向不带参数并返回指向 cmdData_t 的指针函数的数组。通过阅读声明可以知道它的用法:首先对 cmdStreamTaskPtr 进行下标操作,因为下标操作比解引用操作具有更高的优先级,然后对结果进行解引用操作,最后对 void(空)进行调用,如果函数调用的结果被解引用,我们最终得到一个 cmdData_tstatic 存储期限定符适用于数组,并且是多余的,因为全局变量默认为静态。此外,代码 {[0 ... MAX_STREAMS - 1]= NULL} 使用了一个范围指定初始化器,这是 C 语言的 GNU 扩展,将所有内容设置为 null,这是多余的,原因有三个:未指定的初始化列表元素会自动设置为零,静态存储变量会自动设置为零,而后面的代码会将数组设置为零。


5
"static"永远不会多余。 如果这实际上是一个全局变量,"static"会给它内部链接。 - melpomene
6
全局变量默认是静态的。--> 不是。 - chux - Reinstate Monica
2
@chux:嗯,这说法有一半是对的。全局对象确实具有静态存储期。但仍然不正确地说static在这里是多余的,因为它影响的是链接,而不是存储期。这对于一个存储类说明符来说是很烦人的事情。 - Eric Postpischil
@EricPostpischil 确实全局对象具有_static storage_持续时间。是的,说“static”是多余的是错误的 - 你可以再说一遍 - DORD ;-) - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接