长度为N的指针数组,指向返回指针的函数。

16

这个问题是面试中问我的!我真的很困惑。

  • 如何声明一个包含N个指向函数的指针的数组,它们返回指向函数的指针,这些函数又返回指向字符的指针?

有没有人能帮忙解答一下?


3
多么愚蠢的面试问题。互联网存在的原因就是让我们在需要时查找晦涩语法,而不必将大脑塞满它们。 - Doug T.
8
apt-get install cdecl; echo declare array of pointer to function returning pointer to function returning pointer to char | cdecl; >>> char *(*(*var[])())() - Mehrdad Afshari
1
@Doug T:我觉得这听起来很合理。不幸的是,在 C 语言中知道如何处理复杂的声明是一项非常有用的技能。 - David Thornley
@David 即使它不是晦涩的语法,我认为它并没有太大的价值。这是一些容易被学习和遗忘的知识——非常适合缓存。我更想知道某人是否从根本上理解了概念。如果我给他们一个带有奇怪声明语法的作弊表,他们能否坐下来编写一个合理的程序?他们能否深入地讨论问题? - Doug T.
@Doug T:这就是为什么,如果我问那个问题,我会对方法比最终答案更感兴趣。面试问题与认证考试问题不同。重要的不是你能否从cdecl中背出Mehrdad的答案,虽然这很令人印象深刻但并非必要的,但是如果你变得非常困惑,那可不是一个好迹象。 - David Thornley
6个回答

34

类型定义是为了懒人。这里有一种直接而机械化的方法来解决复杂的声明:

          a                 -- a
          a[N]              -- is an N-element array
         *a[N]              -- of pointers
        (*a[N])()           -- to functions
       *(*a[N])()           -- returning pointers
      (*(*a[N])())()        -- to functions
     *(*(*a[N])())()        -- returning pointers
char *(*(*a[N])())()        -- to char.  
因此,答案在char *(*(*a[N])())();附近。我说“附近”,因为从未指定函数需要什么参数。
这是一个恶心的面试问题(我个人认为这样丑陋的类型真的很少见),但它确实可以让面试官了解您对声明符的理解程度。要么就是他们很无聊,只是想看看他们能否让你的大脑死机。
编辑:大多数人都建议使用typedef。我唯一推荐使用typedef的时候是如果该类型被打算成真正的不透明类型(即程序员不能直接操纵该类型,而是把它传递给API,有点像FILE类型)。否则,如果程序员需要直接操作该类型的对象,则我认为最好在声明中提供所有那些信息,尽管看起来很丑。例如,像这样的东西:
 NameFuncPickerPointer a[N];

这并没有告诉我如何实际使用a[i]。我不知道a[i]是否可调用,或者它返回什么,或者它应该接受哪些参数(如果有),或者其他任何信息。我必须去寻找typedef。

typedef char *NameFunc();
typedef NameFunc *NameFuncPicker();
typedef NameFuncPicker *NameFuncPickerPointer;

从那个难题中推断出如何编写实际调用其中一个函数的表达式。如果使用“裸露”的、未经过typedef定义的声明,则我立即知道调用的结构是什么。

char *theName = (*(*a[i])())();

现在,即使我不是C程序员,我也能理解这个。 - Lieven Keersmaekers
1
关于命名,我想看到StringGetter_Getter a[N]StringGetter_Getter_Array a或者FunctionTable a。它必须在代码上下文中有一定的意义,我宁愿看到StringGetter_Getter在各个地方重复出现,也不愿看到char *(*(*)())()这样的东西。但是这很容易陷入与是否命名常量相同的争论:“如果有人使用80,我不想去查找DEFAULT_HTTP_PORT的值,我想在源代码中看到80”。作为程序员,间接引用是我们所有问题的根源和解决方案。 - Steve Jessop
最终,如果你的C代码有返回工厂函数的工厂函数表,那么你可能在去“痛苦复杂的企业Java”课程的路上走错了;-) - Steve Jessop

6
typedef char* (* tCharRetFunc)();
typedef tCharRetFunc (* tFuncRetCharFunc)();

tFuncRetCharFunc arr[N];

我认为这个问题的设计是为了测试面试者是否理解typedef,并给出一个清晰且简明的解决方案,就像这个答案一样,或者是像其他答案中给出的技术上恶劣的解决方案。因此,作为这类问题来说,它是相当不错的。 - Elemental

3
将大问题分解为小问题:
/* char_func_ptr is pointer to function returning pointer to char */
typedef char* (*char_func_ptr)();

/* func_func_ptr is a pointer to function returning above type */
typedef char_func_ptr (*func_func_ptr)();

/* the_array is array of desired function pointers */
func_func_ptr the_array[42];

1

一个包含N个指向返回指针的函数的指针数组,返回一个字符:

int (*(*arr_fp[n])(void))(void)

0

这是您正在寻找的吗:

typedef char* charptr;
typedef charptr (*innerfun)();
typedef innerfun (*outerfun)();

const size_t N = 10;
outerfun my_outerfun_array[N];

我希望我的答案是正确的,对我来说这似乎是一个奇怪的问题,特别是在面试中 :(


0

像Christopher告诉你的那样使用typedef是声明这种东西的唯一人性化方式。没有typedef,它将变成:

char *(*(*arr[10])(void ))(void );

(是的,我得作弊了,运行 cdecl> 声明一个数组arr,大小为10,元素类型为指向函数(无参数)返回指向函数(无参数)返回指向字符的指针)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接