我正在尝试找出一些 C 声明。这些 C 声明的含义是什么?
double (*b)[n];
double (*c[n])();
double (*d())[n];
double (*b)[n];
b 是指向 n 个双精度数组的指针
double (*c[n])();
c 是一个包含 n 个指向函数的指针数组,该函数接受未指定数量的参数并返回 double
double (*d())[n];
d 是一个函数,它接受未指定数量的参数并返回指向 n 个双精度数组的指针
通常,为了在您的脑海中解析这些类型的声明,请采用以下方法。让我们看看最后一个声明,例如
double (*d())[n];
对 d 做的第一件事是什么?它是用 () 调用的,因此它是一个接受未指定数量的参数和 returnig 的函数......结果做了什么?它被取消引用 (*),因此它是一个指向. 然后对结果进行索引,因此它是一个由 n 组成的数组……还剩下什么?一个双,因此是双打。阅读粗体部分,您将得到答案。
让我们看另一个例子
void (*(*f)(int)[n])(char)
在这里,f首先被取消引用,因此它是一个指向...的指针,然后用 (int) 调用它,因此一个函数采用 int 并返回,然后用 [n] 索引结果,因此是一个 n 的数组。结果再次被取消引用,因此指向. 然后结果由 (char) 调用,因此函数采用 char并返回(剩下的都是 void)void。所以 f 是一个指向函数的指针,该函数采用 int 并返回一个 n 指针数组,该数组指向采用 char 并返回 void 的函数。
高温高压
解析C 声明的基本规则是“从右向左阅读,离开一对括号时由内向外跳向右”,即从嵌套最深的一对括号开始,然后向右看。从技术上讲,您必须了解运算符关联性,但它在大多数情况下都足够好用。
现在让我们将此(简化)规则应用于您的问题:
double (*b)[n]; ^
b 是一个
double (*b)[n]; ^
指向的指针
double (*b)[n]; ^^^
和数组
double (*b)[n]; ^^^^^^
双打。
double (*c[n])(); ^^^^
c 是一个数组
double (*c[n])(); ^
指向
double (*c[n])(); ^^
职能
double (*c[n])(); ^^^^^^
返回双倍。
double (*d())[n]; ^^^
d 是一个函数
double (*d())[n]; ^
返回一个指向
double (*d())[n]; ^^^
一个数组
double (*d())[n]; ^^^^^^
双打
在大多数 *nixes 上都有一个简洁的实用程序,称为cdecl,它采用 C 声明字符串并将其转换为自然语言句子。
让我们试试这个方法。
首先,你应该熟悉这三个符号:
1. * -- 一个指针。 2. [] -- 一个数组。 3. () -- 一个函数。(注意:不是括号)
我们以“double (*d())[n]”为例。
第一步是找出声明中的标识符,标识符是变量的名称,这里是“d”。
(一世) ——什么是“d”? -------------------------------------------------- ---------------------- 查看标识符的右侧,看看是否有 "[]" 或 "()" : ...d[]...: d 是一个数组。 ...d()...: d 是一个函数。 如果两者都没有,请查看左侧,看看是否有“*”: ...*d...: d 是一个指针。 -------------------------------------------------- ----------------------
现在我们发现 d 是一个函数。用 x 代替 d(),则声明变为“double (*x)[n]”
(二) ——什么是“x”? -------------------------------------------------- ---------------------- 重复(i),我们发现x是一个指针。 这意味着, d 是一个返回指针的函数。 -------------------------------------------------- ----------------------
用y代替*x,则声明变为“double y[n]”
㈢ ——什么是“y”? -------------------------------------------------- ---------------------- 重复(i),我们发现y是n个元素的数组。 这意味着,d 是一个函数,它返回一个指向 n 个元素的数组的指针。 -------------------------------------------------- ----------------------
用z代替y[n],则声明变为“双z”
(四) ——什么是“z”? -------------------------------------------------- ---------------------- 重复 (i),我们发现 z 是一个双精度数。 这意味着, d 是一个函数,它返回一个指向 n 个双精度元素的数组的指针。 -------------------------------------------------- ----------------------
让我们看另一个表达式:
无效 (*(*f)(int)[n])(char)
1. 我们找到 f。 2. f 是一个指针。*f -> 一个 无效 (*a(int)[n])(char) 3. a 是一个函数。a() -> b 无效 (*b[n])(char) --f 是指向函数的指针(带有 int 参数)-- 4. b 是一个数组。b[] -> c 无效 (*c)(char) --f 是一个指向函数的指针,该函数返回一个数组(包含 n 个元素)-- 5. c 是一个指针。*c -> d 无效d(字符) --f 是一个指向函数的指针,该函数返回一个包含 n 个指针的数组-- 6. d 是一个返回 void 的函数。 --f 是一个指向函数的指针,它返回一个包含 n 个指向函数(带有 char 参数)的指针的数组,返回 void--
有两个很好的资源可以理解“C 胡言乱语”:
cdecl.org 的输出:
double (*c[n])()
: 语法错误(n
此处无效)double (*c[])()
: 将 c 声明为指向返回 double 的函数的指针数组