printf()和cout在c++中的区别是什么?


当前回答

TL;DR:在相信在线随机评论之前,一定要自己做研究,考虑生成的机器代码的大小、性能、可读性和编码时间,包括这一条。

我不是专家。我碰巧听到两个同事在讨论如何避免在嵌入式系统中使用c++,因为会导致性能问题。有趣的是,我基于一个真实的项目任务做了一个基准测试。

在该任务中,我们必须向RAM写入一些配置。喜欢的东西:

咖啡=热 糖=没有 牛奶=乳房 mac = AA: BB: CC:弟弟:EE: FF

这是我的基准测试程序(是的,我知道OP询问printf(),而不是fprintf()。试着捕捉本质,顺便说一下,OP的链接指向fprintf()。)

C程序:

char coffee[10], sugar[10], milk[10];
unsigned char mac[6];

/* Initialize those things here. */

FILE * f = fopen("a.txt", "wt");

fprintf(f, "coffee=%s\nsugar=%s\nmilk=%s\nmac=%02X:%02X:%02X:%02X:%02X:%02X\n", coffee, sugar, milk, mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]);

fclose(f);

c++程序:

//Everything else is identical except:

std::ofstream f("a.txt", std::ios::out);

f << "coffee=" << coffee << "\n";
f << "sugar=" << sugar << "\n";
f << "milk=" << milk << "\n";
f << "mac=" << (int)mac[0] << ":"
    << (int)mac[1] << ":"
    << (int)mac[2] << ":"
    << (int)mac[3] << ":"
    << (int)mac[4] << ":"
    << (int)mac[5] << endl;
f.close();

我尽了最大努力打磨它们,然后把它们都绕了10万次。以下是调查结果:

C程序:

real    0m 8.01s
user    0m 2.37s
sys     0m 5.58s

c++程序:

real    0m 6.07s
user    0m 3.18s
sys     0m 2.84s

目标文件大小:

C   - 2,092 bytes
C++ - 3,272 bytes

结论:在我非常特定的平台上,使用非常特定的处理器,运行非常特定版本的Linux内核,运行一个非常特定版本的GCC编译的程序,以完成一个非常特定的任务,我会说c++方法更适合,因为它运行得更快,可读性更好。另一方面,C提供了小的内存占用,在我看来,这几乎没有什么意义,因为程序大小不是我们所关心的。

记住,YMMV。

其他回答

我引用一下:

在高层术语中,主要的区别是类型安全(cstdio 没有它),性能(大多数iostreams实现都有 比cstdio慢)和可扩展性(iostreams允许 自定义输出目标和用户定义类型的无缝输出)。

一个是输出到标准输出的函数。另一个是一个对象,它提供了几个成员函数和输出到stdout的操作符<<的重载。我可以列举更多的不同之处,但我不确定你想要的是什么。

cout<< "Hello";
printf("%s", "Hello"); 

两者都用于打印值。它们有完全不同的语法。c++两者都有,C 只有printf。

来自c++常见问题解答:

[15.1] Why should I use <iostream> instead of the traditional <cstdio>? Increase type safety, reduce errors, allow extensibility, and provide inheritability. printf() is arguably not broken, and scanf() is perhaps livable despite being error prone, however both are limited with respect to what C++ I/O can do. C++ I/O (using << and >>) is, relative to C (using printf() and scanf()): More type-safe: With <iostream>, the type of object being I/O'd is known statically by the compiler. In contrast, <cstdio> uses "%" fields to figure out the types dynamically. Less error prone: With <iostream>, there are no redundant "%" tokens that have to be consistent with the actual objects being I/O'd. Removing redundancy removes a class of errors. Extensible: The C++ <iostream> mechanism allows new user-defined types to be I/O'd without breaking existing code. Imagine the chaos if everyone was simultaneously adding new incompatible "%" fields to printf() and scanf()?! Inheritable: The C++ <iostream> mechanism is built from real classes such as std::ostream and std::istream. Unlike <cstdio>'s FILE*, these are real classes and hence inheritable. This means you can have other user-defined things that look and act like streams, yet that do whatever strange and wonderful things you want. You automatically get to use the zillions of lines of I/O code written by users you don't even know, and they don't need to know about your "extended stream" class.

另一方面,printf要快得多,因此在非常特定和有限的情况下,可以优先使用它而不是cout。总是先做侧写。(例如,参见http://programming-designs.com/2009/02/c-speed-test-part-2-printf-vs-cout/)

人们经常声称printf要快得多。这在很大程度上是一个神话。我刚刚测试了一下,结果如下:

cout with only endl                     1461.310252 ms
cout with only '\n'                      343.080217 ms
printf with only '\n'                     90.295948 ms
cout with string constant and endl      1892.975381 ms
cout with string constant and '\n'       416.123446 ms
printf with string constant and '\n'     472.073070 ms
cout with some stuff and endl           3496.489748 ms
cout with some stuff and '\n'           2638.272046 ms
printf with some stuff and '\n'         2520.318314 ms

结论:如果你只想要换行,使用printf;否则,cout几乎一样快,甚至更快。更多细节可以在我的博客上找到。

需要澄清的是,我并不是说iostreams总是比printf更好;我只是想说,你应该根据真实的数据做出明智的决定,而不是基于一些常见的、误导性的假设而胡乱猜测。

更新:这里是我用于测试的完整代码。使用g++编译,没有任何其他选项(除了用于计时的-lrt)。

#include <stdio.h>
#include <iostream>
#include <ctime>

class TimedSection {
    char const *d_name;
    timespec d_start;
    public:
        TimedSection(char const *name) :
            d_name(name)
        {
            clock_gettime(CLOCK_REALTIME, &d_start);
        }
        ~TimedSection() {
            timespec end;
            clock_gettime(CLOCK_REALTIME, &end);
            double duration = 1e3 * (end.tv_sec - d_start.tv_sec) +
                              1e-6 * (end.tv_nsec - d_start.tv_nsec);
            std::cerr << d_name << '\t' << std::fixed << duration << " ms\n"; 
        }
};

int main() {
    const int iters = 10000000;
    char const *text = "01234567890123456789";
    {
        TimedSection s("cout with only endl");
        for (int i = 0; i < iters; ++i)
            std::cout << std::endl;
    }
    {
        TimedSection s("cout with only '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << '\n';
    }
    {
        TimedSection s("printf with only '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("\n");
    }
    {
        TimedSection s("cout with string constant and endl");
        for (int i = 0; i < iters; ++i)
            std::cout << "01234567890123456789" << std::endl;
    }
    {
        TimedSection s("cout with string constant and '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << "01234567890123456789\n";
    }
    {
        TimedSection s("printf with string constant and '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("01234567890123456789\n");
    }
    {
        TimedSection s("cout with some stuff and endl");
        for (int i = 0; i < iters; ++i)
            std::cout << text << "01234567890123456789" << i << std::endl;
    }
    {
        TimedSection s("cout with some stuff and '\\n'");
        for (int i = 0; i < iters; ++i)
            std::cout << text << "01234567890123456789" << i << '\n';
    }
    {
        TimedSection s("printf with some stuff and '\\n'");
        for (int i = 0; i < iters; ++i)
            printf("%s01234567890123456789%i\n", text, i);
    }
}