3

我正在阅读此处发布的 K&R 第 7 章中问题的解决方案。基本上,程序会根据程序的名称(“upper”或“lower”)将标准输入转换为小写或大写。它似乎将转换函数的名称存储在某种字典中,如下所示:

int (*convcase[2])(int) = {toupper, tolower};

然后根据程序的名称是以 au 还是 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) 何时/为何使用这种设置。当您有多个可能的函数调用时,它只是一个类似宏的快速工具来节省一些空间吗?

4

1 回答 1

3
  1. convcase是两个函数指针的数组;它不是一个指针。数组表达式在需要指针的地方使用时将隐式转换为指针。
  2. 那不是演员表。它指定函数接受int参数,就像toupperandtolower函数一样。
  3. convcase用函数指针toupper和初始化tolower
  4. 我认为这个问题是关于函数指针的。当您希望函数指针抽象时,请使用函数指针。我建议这个例子是对函数指针的不必要使用。在这种情况下,根据用户输入更改convcase[0]或更改为西班牙语或日语的能力更有可能保证使用函数指针。convcase[1]此外,函数指针可用于参数中以提供额外的抽象。例如,qsort函数能够对任何类型的数组进行排序,因为它使用函数指针来比较对象。这是一个使用函数作为比较器int对输入进行排序的示例。int_compare
#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;
}
于 2013-03-10T18:01:18.327 回答