我正在阅读K& R第7章here发布的问题解决方案。基本上,程序会根据程序名称(“上”或“下”)将标准输入转换为小写或大写。它似乎将转换函数的名称存储在某种字典中,如下所示:
int (*convcase[2])(int) = {toupper, tolower};
以后访问这些函数取决于程序名称是以u还是l:
开头if(argc > 0)
{
if(toupper((unsigned char)argv[0][0]) == 'U')
{
func = 0;
}
else
{
func = 1;
}
while((ch = getchar()) != EOF)
{
ch = (*convcase[func])((unsigned char)ch);
putchar(ch);
}
}
我理解代码块正在做什么,但我从未见过像convcase的初始声明那样的东西。它似乎是宏,枚举和数组的某种奇怪组合。任何人都可以解释(1)为什么convcase是一个指针; (2)名称之后的(int)演员是什么; (3)该声明中究竟是什么样的toupper和tolower,因为它们不是char; s; (4)何时/为何使用这种设置。当你有多个可能的函数调用时,它只是一个快速的类宏工具来节省一些空间吗?
答案 0 :(得分:3)
convcase
是一个包含两个函数指针的数组;它不是指针。当数组表达式在指向期望的位置使用时,它将隐式转换为指针。int
参数,如toupper
和tolower
函数那样。convcase
和toupper
初始化tolower
。convcase[0]
或convcase[1]
更改为西班牙语或日语的能力更有可能保证在这种情况下使用函数指针。另外,函数指针可以在参数中使用以提供额外的抽象。例如,qsort函数能够对任何类型的数组进行排序,因为它使用了对象的 comparer 的函数指针。以下是使用int
函数将int_compare
输入排序为 comparer 的示例。#define nelem(array) (sizeof (array) / sizeof *(array))
int int_compare(const void *p1, const void *p2) {
int x = *(int *)p1, y = *(int *)p2;
return (x > y) - (y > x);
}
int main(void) {
int value[16];
for (size_t x = 0; x < nelem(value); x++) {
if (scanf("%d", &value[x]) != 1) {
break;
}
}
qsort(value, sizeof *value, x, int_compare);
return 0;
}