C语言中`void *ptr[N](int)`和`void(*ptr)[N](int)`的区别是什么?[副本]

ccgok5k5  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(103)

此问题已在此处有答案

How to decipher complex pointer declarations in C?(4个答案)
上个月关门了。
假设我有void (*ptr[3])(int)void (*ptr)[3](int)
第一个工作如预期。但第二个抛出一个错误。
我两个都试过了,但还是找不到问题所在。错误内容为:
“..error:declaration of 'ptr' as array of functions void(*ptr)3;“

kokeuurv

kokeuurv1#

void (*ptr)[3](int)与声明ptr是指向函数数组的指针相同,这是不允许的。你不能有函数数组。

typedef void(functype)(int);
functype ptr[3];              // error

你需要的很可能是一个函数 * 指针 * 数组,这就是你的工作声明void (*ptr[3])(int)所创建的。

typedef void(functype)(int);
functype* ptr[3];
//      ^

用法示例:

void a(int x) {}
void b(int x) {}
void c(int x) {}

int main(void) {
    typedef void(functype)(int);

    functype* ptr[3] = {a,b,c};
}
9udxz4iz

9udxz4iz2#

无论是谁提出了指向函数或数组的指针的语法,背后都没有太多的理论依据--很可能只是偶然发生的。这里有一些规则:

  • 函数并不真正存在于表达式中,只有函数指针才存在。C17 6.3.2.1 §4:
  • function designator* 是一个具有函数类型的表达式。除非它是sizeof运算符或一元&运算符的操作数,否则类型为“函数返回类型”的函数指示符将转换为类型为“指向函数返回类型的指针”的表达式。
  • 声明/初始化与表达式中的运算符优先级“协调”。这意味着int*p[3]总是意味着“3 int指针数组”,而不是“指向3 int数组的指针”,就像表达式*p[3]总是意味着“访问第4个元素,然后解引用”一样。

由于上述原因,编译器在面对非法语法时可能很难产生合理的诊断。在这种情况下,错误int p [3] (void);和错误int (*p) [3] (void);给予在gcc和clang中相同的诊断信息,有点“将'p'声明为函数数组”的味道。尽管后者如何被认为是一个“函数数组”并不明显。事实上,前者是一个函数数组,后者是一个指向函数数组的指针-两者都不允许。
正如我们所知,几乎没有人理解这种混乱,包括那些为gcc和clang编写编译器诊断程序的人。少数人假装他们这样做是那些愿意花荒谬的时间分析不必要的模糊表达以下“顺时针螺旋”,直到他们的眼睛看起来像顺时针螺旋......别这样

这里的第一条规则是在使用函数指针时 * 始终 * 使用typedef,没有例外。

这里有一个小FAQ:

int ptr1 (void);           // OK. Function
int (ptr2) (void);         // Weird but OK. Still a function
int ptr3 [3] (void);       // Invalid declaration - array of functions
int (*ptr4) (void);        // OK. Pointer to function
int (*ptr5 [3]) (void);    // OK. Array of pointers to functions
int (*ptr6) [3] (void);    // Invalid declaration - pointer to array of functions
int ((*(*ptr4)(void))[3]); // Madness, pointer to a function returning a pointer to array of 3 int

强烈建议的做法:

typedef int func_t (void);   // function type
func_t* func;                // function pointer
func_t* func[3];             // array of function pointers
func_t* const func = f;      // read-only function pointer, can't be reassigned
func_t* const func[3] =      // read-only array of function pointers, can't be reassigned
{ ... };

相关问题