C 语言迷思 - 最短的函数声明调用?

这篇文章源于 V2EX 上的一个 [c 语言谜题] 程序填空,老程序员来做做。原题是这样的

#include <stdio.h>

int main() {
    [] 
    printf("%p\n", *********************************p);
    return 0;
}

在上面的 C 语言代码 [] 标记内加入一条语句,使得:

  1. 程序编译通过,无错误(警告随意);链接通过,无错误(警告随意)
  2. 程序能够运行,无崩溃和运行时错误
  3. 源代码为 .c 文件
  4. 如果用 vs, 则使用 Release 配置;用 gcc 也行
  5. 加入的语句不能忽略分号
  6. printf 一句必须能够正常输出内容

问:

  1. 要加入的语句的长度最小是几(含分号、空白、字符、符号等)?
  2. 这个最小长度的语句的 sha256 哈希值是多少?

ps:为了确保为数不多的趣味性,请勿直接贴出语句

看到这个题目,映入眼帘的第一个答案就是能否声明一个简短的变量,要做到字符最短,肯定使用最短的关键字,那么,肯定是 int。因为输出是 ***p ,所以变量名必须是 p 。所以,我们第一次给的答案就是下面这样

#include <stdio.h>

int main() {
    int p; 
    printf("%p\n", *********************************p);
    return 0;
}

编译肯定报错,不行你看

[root@localhost ~]# gcc main.c
main.c:5:81: error: indirection requires pointer operand ('int' invalid)
    printf("%p\n", *********************************p);
                                                                                ^~
1 error generated

赋予一个值编译也会报错,因为我们并没有修正这个错误

#include <stdio.h>

int main() {
    int p=9; 
    printf("%p\n", *********************************p);
    return 0;
}

声明一个指针也会报错

#include <stdio.h>

int main() {
    int*p=9; 
    printf("%p\n", *********************************p);
    return 0;
}

声明一个指针然后赋值也会报错

#include <stdio.h>

int main() {
    int*p=9; 
    printf("%p\n", *********************************p);
    return 0;
}

如果声明为一个函数呢?最短的函数肯定是没有返回值的,所以,我们定义如下

#include <stdio.h>

int main() {
    p(){}; 
    printf("%p\n", *********************************p);
    return 0;
}

编译结果如下

main.c:4:5: warning: implicit declaration of function 'p' is invalid in C99 [-Wimplicit-function-declaration]
    p(){}; 
    ^
main.c:4:8: error: expected ';' after expression
    p(){}; 
       ^
       ;
1 warning and 1 error generated.

注意那个 main.c:4:8: error: expected ';' after expression 导致这个错误的发生,是因为我们没有给函数添加返回值类型。那就加上试一试呗

#include <stdio.h>

int main() {
    int p(){}; 
    printf("%p\n", *********************************p);
    return 0;
}

然而,在最新的编译器上,这是不通过的,因为这是一个函数定义,C 语言是不允许在函数内再定义一个函数的。

main.c:4:12: error: function definition is not allowed here
    int p(){}; 
           ^
main.c:5:82: error: use of undeclared identifier 'p'
    printf("%p\n", *********************************p);
                                                                                 ^
2 errors generated.

我的 gcc 版本如下

gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

既然不能声明一个函数,那我们可以声明一个指向函数的指针对吧

#include <stdio.h>

int main() {
    int(*p)(); 
    printf("%p\n", *********************************p);
    return 0;
}

然后,使用编译和运行都通过了。

其实,还有比这个长的方法,等待大家自己去挖掘吧,我就不一一列举了。

如何调用一个函数

你是不是很疑惑,为什么一个指向函数的指针可以无限的解引用呢 ?

*********************************p;

说到这里,不得不吐槽下 C 语言坑爹的知识点,

「 对于函数指针 p,直接 p() 可以调用,(*p)() 也可以调用 」

所以,看起来,其实 p === *p 啊,按照某个定律 (等等,哪个定律来的,)*p === **p ,以此类推,多少个 * 也是可行的。

我们可以写一个程序实验下

#include <stdio.h>

int main() {
    int(*p)(); 
    printf("%p\n",p);
    printf("%p\n",*p);
    printf("%p\n",**p);
    printf("%p\n",***p);
    return 0;
}

运行的结果如下

0x7ffee14918f8
0x7ffee14918f8
0x7ffee14918f8
0x7ffee14918f8

因为 *p 指向的是地址,所以,你的值可能和我不一样,但是,四个值肯定是一样的。

后记

如果你是初学者,不知道如何定义一个函数指针,可以访问我们的 C 语言基础教程:函数指针

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.