背景
C语言中的变量声明语句由三部分组成:变量的名称,其基本类型和类型修饰符。
有三种类型修饰符:
- 指针
*
(前缀) - 数组
[N]
(后缀) - 功能
()
(后缀)- 您可以在括号内指定一个函数参数列表,但是为了解决这一难题,让我们忽略它而只使用它
()
(从技术上讲,这意味着“该函数可以接受任何类型的参数”)。
- 您可以在括号内指定一个函数参数列表,但是为了解决这一难题,让我们忽略它而只使用它
读取符号的方法如下:
int i; // i is an int
float *f; // f is a pointer to a float
my_struct_t s[10]; // s is an array of 10 my_struct_t
int func(); // func is a function returning an int
问题是我们可以将所有这些混合使用以形成更复杂的类型,例如数组数组或函数指针数组或指向指针数组的指针:
int arr[3][4];
// arr is an array of 3 arrays of 4 ints
int (*fptrs[10])();
// fptrs is an array of 10 pointers to functions returning an int
float *(*p)[16];
// p is a pointer to an array of 16 pointers to float
我如何阅读这些复杂的陈述?
- 从变量名开始。
(name) is ...
- 选择优先级最高的修饰符。
- 阅读:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- 重复2和3,直到修饰符用尽。
- 最后,读取基本类型。
... (base type).
在C语言中,后缀运算符优先于前缀运算符,类型修饰符也不例外。因此,[]
和()
结合第一,然后*
。一对括号中的任何内容(...)
(不要与函数运算符混淆)首先绑定外部的任何内容。
图解示例:
int (*fptrs[10])();
fptrs fptrs is ...
[10] array of 10 ... // [] takes precedence over *
(* ) pointer to ...
() function returning ...
int int
任务
给定一行用C编写的变量声明语句,请使用上述方法输出描述该行的英语表达式。
输入项
输入是单个C语句,其中包括单个基本类型,单个变量名,零个或多个类型修饰符以及结尾的分号。您必须实现上面介绍的所有语法元素,以及:
- 基本类型和变量名称都与正则表达式匹配
[A-Za-z_][A-Za-z0-9_]*
。 - 从理论上讲,您的程序应支持无限数量的类型修饰符。
您可以通过以下方式简化其他C语法元素(也欢迎完全实现):
- 基类型是总是一个字,例如
int
,float
,uint32_t
,myStruct
。诸如此类的东西unsigned long long
将不会被测试。 - 对于数组符号
[N]
,该数字N
将始终是以10为基数的单个正整数。诸如之类的东西int a[5+5]
,int a[SIZE]
或int a[0x0f]
将不会被测试。 - 对于函数符号
()
,如上所述,将完全不指定任何参数。 - 对于空格,将仅使用空格字符
0x20
。您可以将程序限制为特定的空格用法,例如- 基本类型后只能使用一个空格
- 在令牌之间的任何地方都使用空格
- 但是,您不能使用两个或多个连续的空格来传达更多的信息,而不仅仅是令牌分隔符。
根据C语法,以下三个组合无效,因此将不进行测试:
f()()
函数返回函数f()[]
函数返回数组a[]()
N个函数的数组
C开发人员改为使用这些等效形式(并且所有这些都包含在测试用例中):
(*f())()
函数返回指向函数的指针*f()
函数返回指向数组第一个元素的指针(*a[])()
N个指向函数的指针的数组
输出量
输出是单个英语句子。您不需要(但如果您愿意的话)可以尊重英语语法,例如,使用a, an, the
,单数/复数形式以及结束点(句号)。每个单词都应以一个或多个空格(空格,制表符,换行符)分隔,以便使结果易于阅读。
同样,这是转换过程:
- 从变量名开始。
(name) is ...
- 选择优先级最高的修饰符。
- 阅读:
* -> pointer to ...
[N] -> array of N ...
() -> function returning ...
- 重复2和3,直到修饰符用尽。
- 最后,读取基本类型。
... (base type).
测试用例
int i; // i is int
float *f; // f is pointer to float
my_struct_t s[10]; // s is array of 10 my_struct_t
int func(); // func is function returning int
int arr[3][4]; // arr is array of 3 array of 4 int
int (*fptrs[10])(); // fptrs is array of 10 pointer to function returning int
float *(*p)[16]; // p is pointer to array of 16 pointer to float
_RANdom_TYPE_123 (**(*_WTH_is_TH15)())[1234][567];
/* _WTH_is_TH15 is pointer to function returning pointer to pointer to array of
1234 array of 567 _RANdom_TYPE_123 */
uint32_t **(*(**(*(***p)[2])())[123])[4][5];
/* p is pointer to pointer to pointer to array of 2 pointer to function returning
pointer to pointer to array of 123 pointer to array of 4 array of 5 pointer to
pointer to uint32_t */
uint32_t (**((*(**(((*(((**(*p)))[2]))())))[123])[4])[5]);
// Same as above, just more redundant parens
some_type (*(*(*(*(*curried_func())())())())())();
/* curried_func is function returning pointer to function returning pointer to
function returning pointer to function returning pointer to
function returning pointer to function returning some_type */
得分标准
这是一个代码高尔夫挑战。字节数最少的程序获胜。
int arr[3][4];
是an array of 3 arrays of 4 ints
(如您所说),还是an array of 4 arrays of 3 ints
?
;
在行尾包含?