我正在学习C99 -函数指针部分,我的教科书提供了一种使用'typedef'来简化以下代码的方法:
int (*p[4])(int,int) = {&Sum,&Sub,&Mul,&Div};
字符串
↓
typedef int (*OP_TYPE)(int,int);
OP_TYPE p[4]={&Sum,&Sub,&Mul,&Div};
型
我知道“typedef”只能这样使用:例如。
typedef unsigned short int US;
型
如果没有错的话,int
会变成(*OP_TYPE)(int,int)
,第二句话会变成(*OP_TYPE)(int,int)(*p[4])(int,int) = {&Sum,&Sub,&Mul,&Div};
我不明白为什么第二句会是这样。
4条答案
按热度按时间roqulrg31#
关键字
typedef
在语法上与存储修饰符(即auto
、register
、static
等)类似,但初始化部分除外。我猜这是因为早期版本的C编译器在变量声明和类型别名声明之间共享代码。因此,类型别名声明和变量声明看起来差不多相同:
字符串
我想问题是为什么一个人做不到:
型
我没有很好的答案,C语法是这样简单地定义的。我可以猜测,没有锚点,编译器不能正确地解析类型。
那么为什么一个人做不到:
型
答:
它可以解决缺少锚的问题。但是,不能使用它,因为它将与强制转换运算符
(type) expr
冲突。请注意,符号C
可能在范围外定义,从而导致多义性。型
但是,
typeof
扩展(即将推出的C23中的一个功能)有一个解决方法。型
这与编译器扩展以下声明的方式大致相同:
型
此外,使用这个技巧还可以实现复杂类型的简洁、可读的声明。
型
很容易看出,
p
是指向int(int,int)
函数的指针的4元素数组。zf9nrax12#
如果没有错的话,
int
会变成(*OP_TYPE)(int,int)
,第二句话会变成(*OP_TYPE)(int,int)(*p[4])(int,int) = {&Sum,&Sub,&Mul,&Div};
宣言
字符串
不会改变
int
的含义-它会改变OP_TYPE
的含义。首先是一些背景:
C中的声明分为两个主要部分:一个 * 声明说明符 * 的序列,后面是一个逗号分隔的 * 声明符 * 列表。
声明符引入了被声明的对象的名称,沿着还有关于对象的数组性、函数性和指针性的信息。在typedef中,该名称成为类型的别名。
声明符的结构是为了镜像代码中表达式的结构。例如,假设你有一个指向
int
的指针数组arr
,你想访问第i
个元素所指向的整数对象;你可以索引数组并解引用结果,如下所示:型
*arr[i]
的类型是int
;这就是为什么我们将其声明写为型
而不是
型
在表达式中,后缀
[]
下标运算符的操作数是arr
,一元*
解引用运算符的操作数是表达式arr[i]
。这些运算符在声明中遵循相同的优先级规则,因此上面的声明结构。声明内容如下:
型
因此,名为
arr
的对象具有类型“指向int
的指针数组“;类似地,如果你有一个函数指针数组,你想调用其中一个函数,你可以索引数组,解引用结果,然后用任何参数调用结果函数:
型
同样,expression
(*p[i])(a, b)
的类型是int
,因此p
的声明被写入型
而不是
型
声明再次指出,
型
因此,名为
p
的 * 对象 * 具有类型“数组指针指向接受两个int
参数并返回int
的函数“。明白了吗?
那么,
typedef
是如何影响这一点的呢?让我们从一个声明开始,* 不带 *
typedef
:型
这将
OP_TYPE
声明为一个 object,类型为“指向接受两个int
参数并返回int
的函数的指针“。如果我们添加typedef
关键字:型
它改变了声明的含义,使得
OP_TYPE
是类型“指向接受两个int
参数并返回int
的函数的指针“的 * 别名 *。它根本没有改变声明的 * 结构 *,只是改变了声明的含义。因此,您可以编写型
它的意思和
型
一些其他的例子可能有助于把概念带回家;回到前面的例子,如果
型
将
ap
声明为类型为“指向int
的指针的4元素数组“的 * 对象 *,然后型
将
ap
声明为“指向int
的指针的4元素数组“类型的 * 别名 *,这样,型
相当于
型
如果
型
将
blah
声明为“指向int
的N元素数组的指针“类型的对象,则声明型
声明
blah
作为类型“指向int
的N元素数组的指针“的别名。在您提供的示例中,
型
将
US
声明为unsigned short int
类型的对象;因此,型
声明
US
作为类型unsigned short int
的别名。声明(以及
typedefs
)可以变得任意复杂:foo
是一个指向函数的指针,该函数返回一个指向指针数组的指针,该指针数组指向接受double
参数并返回指向int
的指针的函数。添加typedef
:将
foo
改变为类型“返回指向指针数组的指针的函数到接受double
参数并返回指向int
的指针的函数”的别名;再次,相当于写
carvr3hs3#
int
没有被typedef
“改变”。typedef unsigned short int US;
没有“改变”unsigned short int
,它定义了标识符US
来表示与unsigned short int
相同的类型。同样,typedef int (*OP_TYPE)(int,int)
定义标识符OP_TYPE
,以表示与int (*)(int, int)
相同的类型(指向返回int
的函数的指针,参数类型列表为int, int
)。从句法上讲,
typedef
类似于存储类说明符,但它定义了一个“typedef名称”而不是声明变量。比较typedef int (*OP_TYPE)(int, int);
和static int (*op)(int, int);
。OP_TYPE
是typedef名称,op
是变量。OP_TYPE
和op
具有相同的类型int (*)(int, int)
。OP_TYPE
可以用作类型在随后的声明中,使static OP_TYPE op;
等效于static int (*op)(int, int);
zujrkrfu4#
OP_TYPE是一个函数指针类型。下面是一个例子:
字符串
使用
型