& # 39; printf # 39;和& # 39;cout # 39;在c++中

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

455187 次浏览

并且我报价:

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

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

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

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

c++常见问题解答:

[15.1]为什么我应该使用<iostream>而不是传统的<cstdio>?

增加类型安全性,减少错误,允许可扩展性,并提供可继承性。

printf()可以说没有被破坏,而scanf()尽管容易出错,但可能是可行的,然而两者都受到c++ I/O所能做的事情的限制。c++ I/O(使用<<>>)相对于C(使用printf()scanf()):

  • 更类型安全:在<iostream>中,I/O的对象类型为 编译器静态地知道。在 相比之下,<cstdio>使用“%”字段来
  • 更不容易出错:使用<iostream>,没有冗余 必须一致的"%"标记 实际的对象是I/O。 删除冗余将删除一个类 李的错误。< / >
  • 可扩展:c++ <iostream>机制允许新的用户定义 类型被I/O而不中断 现有的代码。想象一下如果 每个人都在同时补充 新的不兼容的“%”字段 printf()scanf()?!李< / >
  • 可继承:c++ <iostream>机制是从实际类构建的 例如std::ostreamstd::istream。不像<cstdio> FILE*,这些是真正的类和 因此可继承的。这意味着你可以 还有其他用户定义的东西吗 外表和行为都像溪流,然而 做什么稀奇古怪的事 你想要的东西。你自动 可以使用无数行的 用户编写的I/O代码 甚至知道,他们也不需要知道 了解你的“延伸流” 李课。< / >

另一方面,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几乎一样快,甚至更快。更多细节可以在我的博客中找到。

需要澄清的是,我并不是想说__abc0总是比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);
}
}

对我来说,真正的区别是让我选择'cout'而不是'printf':

1) & lt; & lt;操作符可以为我的类重载。

2)输出流cout可以很容易地更改为一个文件: (:复制粘贴:)

#include <iostream>
#include <fstream>
using namespace std;


int main ()
{
cout << "This is sent to prompt" << endl;
ofstream file;
file.open ("test.txt");
streambuf* sbuf = cout.rdbuf();
cout.rdbuf(file.rdbuf());
cout << "This is sent to file" << endl;
cout.rdbuf(sbuf);
cout << "This is also sent to prompt" << endl;
return 0;
}

3)我发现cout更具可读性,特别是当我们有很多参数时。

一个带有cout问题是格式化选项。在printf中格式化数据(precision, justification等)更容易。

对于原语,使用哪个原语可能并不重要。当你想输出复杂的对象时它才有用。

例如,如果你有一门课,

#include <iostream>
#include <cstdlib>


using namespace std;


class Something
{
public:
Something(int x, int y, int z) : a(x), b(y), c(z) { }
int a;
int b;
int c;


friend ostream& operator<<(ostream&, const Something&);
};


ostream& operator<<(ostream& o, const Something& s)
{
o << s.a << ", " << s.b << ", " << s.c;
return o;
}


int main(void)
{
Something s(3, 2, 1);


// output with printf
printf("%i, %i, %i\n", s.a, s.b, s.c);


// output with cout
cout << s << endl;


return 0;
}

现在,上面的内容可能看起来并不是很好,但是让我们假设您必须在代码中的多个地方输出这些内容。不仅如此,假设您添加了一个字段“int d”。使用cout,您只需要在一个地方更改它。然而,使用printf,你可能需要在很多地方改变它,不仅如此,你还需要提醒自己输出哪些。

尽管如此,使用cout,您可以减少大量用于维护代码的时间,不仅如此,如果您在新应用程序中重用对象“Something”,您实际上不必担心输出。

当然,你可以把“something”写得更好一点,以保持维护:

#include <iostream>
#include <cstdlib>


using namespace std;


class Something
{
public:
Something(int x, int y, int z) : a(x), b(y), c(z) { }
int a;
int b;
int c;


friend ostream& operator<<(ostream&, const Something&);


void print() const { printf("%i, %i, %i\n", a, b, c); }
};


ostream& operator<<(ostream& o, const Something& s)
{
o << s.a << ", " << s.b << ", " << s.c;
return o;
}


int main(void)
{
Something s(3, 2, 1);


// Output with printf
s.print(); // Simple as well, isn't it?


// Output with cout
cout << s << endl;


return 0;
}

如果有人想做更多的测试(Visual Studio 2008,可执行文件的发布版本),cout vs. printf的一点扩展测试,增加了'double'的测试:

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


class TimedSection {
char const *d_name;
//timespec d_start;
clock_t d_start;


public:
TimedSection(char const *name) :
d_name(name)
{
//clock_gettime(CLOCK_REALTIME, &d_start);
d_start = clock();
}
~TimedSection() {
clock_t end;
//clock_gettime(CLOCK_REALTIME, &end);
end = clock();
double duration = /*1e3 * (end.tv_sec - d_start.tv_sec) +
1e-6 * (end.tv_nsec - d_start.tv_nsec);
*/
(double) (end - d_start) / CLOCKS_PER_SEC;


std::cerr << d_name << '\t' << std::fixed << duration * 1000.0 << " ms\n";
}
};




int main() {
const int iters = 1000000;
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);
}
{
TimedSection s("cout with formatted double (width & precision once)");
std::cout << std::fixed << std::scientific << std::right << std::showpoint;
std::cout.width(8);
for (int i = 0; i < iters; ++i)
std::cout << text << 8.315 << i << '\n';
}
{
TimedSection s("cout with formatted double (width & precision on each call)");
std::cout << std::fixed << std::scientific << std::right << std::showpoint;


for (int i = 0; i < iters; ++i)
{ std::cout.width(8);
std::cout.precision(3);
std::cout << text << 8.315 << i << '\n';
}
}
{
TimedSection s("printf with formatted double");
for (int i = 0; i < iters; ++i)
printf("%8.3f%i\n", 8.315, i);
}
}

结果是:

cout with only endl    6453.000000 ms
cout with only '\n'    125.000000 ms
printf with only '\n'    156.000000 ms
cout with string constant and endl    6937.000000 ms
cout with string constant and '\n'    1391.000000 ms
printf with string constant and '\n'    3391.000000 ms
cout with some stuff and endl    9672.000000 ms
cout with some stuff and '\n'    7296.000000 ms
printf with some stuff and '\n'    12235.000000 ms
cout with formatted double (width & precision once)    7906.000000 ms
cout with formatted double (width & precision on each call)    9141.000000 ms
printf with formatted double    3312.000000 ms
我想说的是,缺乏printf的可扩展性是不完全正确的 在C语言中,它是真的。但是在C语言中,没有真正的类 在c++中,可以重载强制转换操作符,因此,重载char*操作符并像这样使用printf:

Foo bar;
...;
printf("%s",bar);

可以是可能的,如果Foo重载好的操作符。或者你有一个好方法。简而言之,对我来说,printfcout一样可扩展。

我可以看到c++流的技术参数(一般来说…不仅是cout.)是:

  • 类型安全。(顺便说一下,如果我想打印单个'\n',我使用putchar('\n')…我不会用核弹杀死一只昆虫。)

  • 更容易学。(不需要学习“复杂的”参数,只需使用<<>>操作符)

  • 本机使用std::string(对于printfstd::string::c_str(),但对于scanf?)

对于printf,我看到:

  • 更容易,或至少更短(就书写的字符而言)复杂的格式。更有可读性,对我来说(我猜是口味问题)。

  • 更好地控制函数的内容(返回写入了多少字符,并且有%n格式化器:"Nothing printing . "参数必须是一个指向有符号整型的指针,其中存储到目前为止写入的字符数。”(from printf - c++ Reference)

  • 更好的调试可能性。原因和上一个论点一样。

我个人倾向于printf(和scanf)函数,主要是因为我喜欢短行,而且因为我认为打印文本时的类型问题真的很难避免。 我唯一对c风格函数感到遗憾的是std::string不受支持。在将char*赋值给printf之前,我们必须先执行char*(如果我们想读取,则使用std::string::c_str(),但如何写入?)

< p >更多的差异: "printf"返回一个整数值(等于打印的字符数),"cout"不返回任何值

和。

cout << "y = " << 7;不是原子的。

printf("%s = %d", "y", 7);是原子的。

Cout执行类型检查,printf不执行。

没有iostream等价的"% d"

我很惊讶这个问题中的每个人都声称std::coutprintf好得多,即使这个问题只是要求区别。现在,有一个区别——std::cout是c++,而printf是C(然而,你可以在c++中使用它,就像几乎来自C的任何其他东西一样)。printfstd::cout都有各自的优点。

真正的差异

可扩展性

std::cout是可扩展的。我知道人们会说printf也是可扩展的,但这样的扩展在C标准中没有提到(所以你必须使用非标准特性-但甚至不存在常见的非标准特性),而且这样的扩展是一个字母(所以很容易与已经存在的格式冲突)。

printf不同,std::cout完全依赖于运算符重载,因此自定义格式没有问题——你所要做的就是定义一个子例程,将std::ostream作为第一个参数,将你的类型作为第二个参数。因此,不存在命名空间问题——只要你有一个类(不限于一个字符),你就可以为它重载std::ostream

然而,我怀疑很多人会想要扩展ostream(说实话,我很少看到这样的扩展,即使它们很容易创建)。不过,如果你需要的话,它就在这里。

语法

很容易注意到,printfstd::cout使用不同的语法。printf使用标准函数语法,使用模式字符串和变长参数列表。实际上,printf是C语言有它们的原因之一——printf格式太复杂了,没有它们就无法使用。然而,std::cout使用了不同的API——返回自身的operator << API。

一般来说,这意味着C版本会更短,但在大多数情况下,这并不重要。当打印许多参数时,这种差异很明显。如果你必须写类似Error 2: File not found.的东西,假设错误号,并且它的描述是占位符,代码将像这样。这两个例子都相同的工作(好吧,某种程度上,std::endl实际上会刷新缓冲区)。

printf("Error %d: %s.\n", id, errors[id]);
std::cout << "Error " << id << ": " << errors[id] << "." << std::endl;

虽然这看起来并不太疯狂(只是长了两倍),但当您实际格式化参数时,事情就变得更疯狂了,而不仅仅是打印它们。例如,打印像0x0424这样的东西是很疯狂的。这是由std::cout混合状态和实际值引起的。我从未见过像std::setfill这样的语言是类型(当然,c++除外)。printf清楚地分隔实参和实际类型。我真的更喜欢维护它的printf版本(即使它看起来有点神秘)相比iostream版本(因为它包含太多噪音)。

printf("0x%04x\n", 0x424);
std::cout << "0x" << std::hex << std::setfill('0') << std::setw(4) << 0x424 << std::endl;

翻译

这就是printf的真正优势所在。printf格式字符串很好…一个字符串。与operator <<iostream的滥用相比,这使得它非常容易翻译。假设gettext()函数进行了翻译,并且你想要显示Error 2: File not found.,获得前面显示的格式字符串的翻译的代码将如下所示:

printf(gettext("Error %d: %s.\n"), id, errors[id]);

现在,让我们假设我们转换为Fictionish,其中错误编号在描述之后。翻译后的字符串看起来像%2$s oru %1$d.\n。现在,如何在c++中做到这一点?嗯,我不知道。我猜你可以创建假的iostream,它构造printf,你可以将它传递给gettext或其他东西,以用于翻译。当然,$不是C标准,但它是如此常见,在我看来使用它是安全的。

不需要记住/查找特定的整数类型语法

C有很多整数类型,c++也有。std::cout为你处理所有类型,而printf需要特定的语法,取决于整数类型(有非整数类型,但你在实践中使用printf的唯一非整数类型是const char * (C字符串,可以使用std::stringto_c方法获得))。例如,要打印size_t,你需要使用%zu,而int64_t将需要使用%"PRId64"。该表在printf0和printf1处可用。

你不能打印NUL字节,\0

因为printf使用C字符串而不是c++字符串,所以如果没有特定的技巧,它不能打印NUL字节。在某些情况下,可以使用%c'\0'作为参数,尽管这显然是一种hack。

没人关心的差异

性能

更新:原来iostream是如此之慢,它通常比你的硬盘慢(如果你重定向你的程序到文件)。如果你需要输出大量数据,禁用与stdio的同步可能会有所帮助。如果性能是一个真正的问题(而不是写几行到STDOUT),只需使用printf

每个人都认为他们关心绩效,但没有人费心去衡量它。我的答案是无论你使用printf还是iostream, I/O都是瓶颈。我认为printf 可以从快速查看汇编(使用-O3编译器选项用clang编译)更快。假设我的错误示例,printf示例执行的调用比cout示例少得多。这是int mainprintf:

main:                                   @ @main
@ BB#0:
push    {lr}
ldr     r0, .LCPI0_0
ldr     r2, .LCPI0_1
mov     r1, #2
bl      printf
mov     r0, #0
pop     {lr}
mov     pc, lr
.align  2
@ BB#1:

你可以很容易地注意到两个字符串和2 (number)作为printf参数被推入。差不多就是这样;没有别的了。为了便于比较,这是编译为汇编的iostream。不,没有内联;每一个operator <<调用都意味着另一个带有另一组参数的调用。

main:                                   @ @main
@ BB#0:
push    {r4, r5, lr}
ldr     r4, .LCPI0_0
ldr     r1, .LCPI0_1
mov     r2, #6
mov     r3, #0
mov     r0, r4
bl      _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
mov     r0, r4
mov     r1, #2
bl      _ZNSolsEi
ldr     r1, .LCPI0_2
mov     r2, #2
mov     r3, #0
mov     r4, r0
bl      _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
ldr     r1, .LCPI0_3
mov     r0, r4
mov     r2, #14
mov     r3, #0
bl      _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
ldr     r1, .LCPI0_4
mov     r0, r4
mov     r2, #1
mov     r3, #0
bl      _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
ldr     r0, [r4]
sub     r0, r0, #24
ldr     r0, [r0]
add     r0, r0, r4
ldr     r5, [r0, #240]
cmp     r5, #0
beq     .LBB0_5
@ BB#1:                                 @ %_ZSt13__check_facetISt5ctypeIcEERKT_PS3_.exit
ldrb    r0, [r5, #28]
cmp     r0, #0
beq     .LBB0_3
@ BB#2:
ldrb    r0, [r5, #39]
b       .LBB0_4
.LBB0_3:
mov     r0, r5
bl      _ZNKSt5ctypeIcE13_M_widen_initEv
ldr     r0, [r5]
mov     r1, #10
ldr     r2, [r0, #24]
mov     r0, r5
mov     lr, pc
mov     pc, r2
.LBB0_4:                                @ %_ZNKSt5ctypeIcE5widenEc.exit
lsl     r0, r0, #24
asr     r1, r0, #24
mov     r0, r4
bl      _ZNSo3putEc
bl      _ZNSo5flushEv
mov     r0, #0
pop     {r4, r5, lr}
mov     pc, lr
.LBB0_5:
bl      _ZSt16__throw_bad_castv
.align  2
@ BB#6:

然而,老实说,这并不意味着什么,因为I/O本身就是瓶颈。我只是想说明iostream不是更快,因为它是“类型安全”。大多数C实现使用计算goto实现printf格式,因此printf尽可能快,即使编译器没有意识到printf(并不是说它们没有意识到——一些编译器在某些情况下可以优化printf——以\n结尾的常量字符串通常被优化为puts)。

继承

我不知道为什么你想要继承ostream,但我不在乎。这在FILE中也是可能的。

class MyFile : public FILE {}

类型安全

的确,可变长度参数列表没有安全性,但这没关系,因为如果你启用警告,流行的C编译器可以检测到printf格式字符串的问题。事实上,Clang可以在不启用警告的情况下做到这一点。

$ cat safety.c


#include <stdio.h>


int main(void) {
printf("String: %s\n", 42);
return 0;
}


$ clang safety.c


safety.c:4:28: warning: format specifies type 'char *' but the argument has type 'int' [-Wformat]
printf("String: %s\n", 42);
~~     ^~
%d
1 warning generated.
$ gcc -Wall safety.c
safety.c: In function ‘main’:
safety.c:4:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("String: %s\n", 42);
^

printf是函数,而cout是变量。

这里没有提到的两点我认为很重要:

1) cout携带很多行李,如果你还没有使用STL。它向目标文件中添加的代码是printf的两倍多。对于string也是如此,这也是我倾向于使用自己的字符串库的主要原因。

2) cout使用重载的<<操作符,我发现这很不幸。这可能会增加混淆,如果你也使用<<操作符的预期目的(左移)。我个人不喜欢为了与其预期用途无关的目的而重载操作符。

底线:如果我已经在使用STL,我会使用cout(和string)。否则,我倾向于避免它。

我想指出的是,如果你想在c++中使用线程,如果你使用cout,你可以得到一些有趣的结果。

考虑下面的代码:

#include <string>
#include <iostream>
#include <thread>


using namespace std;


void task(int taskNum, string msg) {
for (int i = 0; i < 5; ++i) {
cout << "#" << taskNum << ": " << msg << endl;
}
}


int main() {
thread t1(task, 1, "AAA");
thread t2(task, 2, "BBB");
t1.join();
t2.join();
return 0;
}


// g++ ./thread.cpp -o thread.out -ansi -pedantic -pthread -std=c++0x

现在,输出都被打乱了。它也可以产生不同的结果,试着执行几次:

##12::  ABABAB


##12::  ABABAB


##12::  ABABAB


##12::  ABABAB


##12::  ABABAB

你可以使用printf来纠正错误,也可以使用mutex

#1: AAA
#2: BBB
#1: AAA
#2: BBB
#1: AAA
#2: BBB
#1: AAA
#2: BBB
#1: AAA
#2: BBB

玩得开心!

我不是程序员,但我曾是人为因素工程师。我觉得编程语言应该是容易学习、理解和使用的,这就要求它有一个简单而一致的语言结构。虽然所有的语言都是象征性的,因此,在其核心是任意的,但有惯例,遵循这些惯例使语言更容易学习和使用。

在c++和其他语言中,有大量的函数以函数(参数)的形式编写,这种语法最初是在前计算机时代用于数学中的函数关系。printf()遵循这种语法,如果c++的作者想要创建任何逻辑上不同的方法来读写文件,他们可以使用类似的语法简单地创建一个不同的函数。

在Python中,我们当然可以使用同样相当标准的object.method语法进行打印,即variablename。因为变量是对象,但在c++中它们不是。

我不喜欢cout语法,因为<<操作员不遵守任何规则。它是一个方法或函数,也就是说,它接受一个参数并对它做一些事情。然而,它被写成了一个数学比较运算符。从人为因素的角度来看,这是一个糟糕的方法。

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

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

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

< br > < p >咖啡=热 糖=没有< br > 乳房牛奶= < br > mac = AA: BB: CC:弟弟:EE: FF < / p >

这是我的基准测试程序(是的,我知道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内核版本,运行一个非常具体的海湾合作委员会版本编译的程序,以完成一个非常具体的任务,我会说c++方法更合适,因为它运行得更快,可读性更好。另一方面,C提供了小的内存占用,在我看来,这几乎没有什么意义,因为程序大小不是我们所关心的。

记住,YMMV。