【问题标题】:How to force the compiler to declare functions in C/C++ itself?如何强制编译器在 C/C++ 本身中声明函数?
【发布时间】:2019-10-12 17:24:55
【问题描述】:

问题:
如果我的计算机可以更快地完成,我讨厌编写标题或声明我的函数。
确实如此。
我尝试做的事情:
我试图在main 函数之后声明一个函数foo
但是编译器返回错误:
error: ‘foo’ was not declared in this scope
代码:

#include <iostream>

//no function declaration is allowed, please.
//no other header is allowed, please.

void main() {
    foo();
}

void foo() {
    std::cout << "The compiler is smart now!" << std::endl;
}

如果 gcc/g++ 无法编译此 c++ 代码,我接受更改编译器。
任何回应将不胜感激。

【问题讨论】:

  • 首先,C/C++ 不是一种编程语言,而是两种。一般来说,选择一种语言。
  • 使用宏怎么样?不过,您应该明智地使用。
  • 您可以使用旧的 (K&R) C 编译器。在 K&R C 中,编译器将假定任何使用的未声明函数返回 int 并具有变量参数列表。然而,在现代 C 和 C++ 中(任何比 1990 年代早期都更新的东西)不鼓励依赖它,因为它给程序员提供了很多错误的机会(例如,使用错误的参数调用函数,并将返回值分配给不适当的类型,这两者通常都会给出未定义或错误的行为)。
  • @Peter 这更像是一个答案而不是评论;您可能希望将其格式化为答案。
  • 目前,C++ 构建过程非常糟糕——对于大型代码库来说,编译时间是荒谬的。如果不必在使用之前声明函数,那将在构建过程中造成更大的灾难。所以不,你不能。只需写void foo(); - 否则支持将花费您更多时间。

标签: c++ g++


【解决方案1】:

这对于独立函数是不可能的,因为语言至少需要一个函数原型来调用它。话虽如此,在 C++ 中,您可以使用类来实现类似的结果:

class Main {
public:
    static int main() {
        foo();
        return 0;
    }
    static void foo() { }
};

int main() {
    return Main::main();
}

这是否是一个好的做法是一个不同的讨论。

【讨论】:

  • 这是个好主意!谢谢。
  • 提醒一下,如果您想编写高效且可读的代码并希望拥有小型二进制文件,这是一个非常糟糕的做法。由于在类中定义成员函数会指示编译器隐式使用内联(在编译时将函数调用替换为函数定义),因此它会重复相同的代码,这会增加二进制文件的大小,并且您的代码不太可能在缓存。
  • @BeratPostalcioglu 编译器不需要为所有内联函数执行“内联”(实际上用函数体替换调用)。我确信编译器比大多数程序员都知道它的方法以及如何更好地优化代码。确定此代码是否对您来说效率更高/更低的唯一实际方法是使用编译器在您的机器上进行基准测试,而不是进行过早的微优化。
  • 好主意?伟大的黑客!如果有人更喜欢“不寻常”的解决方案,那么这个解决方案会出现在第一个地方:-)
  • @Ayxan 事实上,盲目地使用“长”内联函数会产生更大的二进制文件和低效的代码。我想强调这不是一个好习惯,尤其是在生产代码中。
【解决方案2】:

您可以使用旧的 (K&R) C 编译器。在 K&R C 中,编译器会隐式假设任何使用的未声明函数返回 int 并具有变量参数列表。

但是,C++ 从未支持该功能。在现代 C(比 1990 年代早期的任何东西)中也强烈反对它,并且在 1999 年的 C 标准中也不允许这样做。原因是这样的特性为程序员错误提供了很多机会(例如,调用带有不正确参数的函数类型,和/或将返回值分配给不适当类型的变量,这两者通常都会产生未定义或其他错误行为)。

【讨论】:

    【解决方案3】:

    我相信你走错路了。

    你的编译器不“知道”你有一个函数声明只是故事的一半。如果您只声明该函数而不是使用它,然后再定义它,可能在不同的翻译单元中,编译器无法在优化期间内联您的代码。现代编译器可以使用链接时间优化,但必须在命令行上启用该功能。

    因此,我建议您重新排序代码,而不是使用(自动生成的)标头中的函数声明。只需将定义移到代码中的用法前面即可。

    在 C++ 中,有时编写“仅标头”代码很有用,而将软件拆分为标头和源文件并不总是最好的主意。这样做有利也有弊,但是使用完整实现的标头通常可以通过内联提供更好的优化。如前所述:也可以通过 LTO。

    顺便说一句:从实现生成头文件的任务已在此处描述:Automatically generate C++ file from header?

    【讨论】:

      【解决方案4】:

      这与 GCC 无关,它与 C++ 通用。新标准引入的模块看起来有望解决该语言的“包含地狱”问题,但这仍然不是您想要的。没有事先声明,无论编译器如何,都无法做你想做的事。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-04-10
        • 2020-06-06
        • 2014-06-04
        • 2016-04-25
        • 1970-01-01
        • 1970-01-01
        • 2013-01-16
        相关资源
        最近更新 更多