K&R似乎更喜欢预增量

ret*_*dev 2 c pre-increment post-increment

我正在通过K&R工作,现在正在练习1-16.我发现到目前为止,书中只使用了预增量.

大多数其他教程书籍和我见过的源代码往往倾向于后增量,除非有明显的影响,例如while循环等.

这是K&R的风格或技术考虑吗?或者我只是需要进一步完成这本书以获得我的答案?!

Gia*_*ian 9

大约1000万年前,在优化编译器之前,这曾经很重要*.它真的不再了.理由store是需要额外的操作才能以天真的方式实现后增量.虽然编译器大多数都没有以这种方式实现它,所以在给定上下文并信任编译器做正确的事情时,更喜欢哪种样式更有意义.

*JimBalter正确地指出这不是一个问题,我不应该暗示它曾经可能有重要意义.

  • 对于C++和迭代器来说,这仍然很重要,其中`operator ++`和`operator - '会因更复杂的操作而过载.但是对于像`int`这样的简单类型,它并不重要. (7认同)

Jen*_*ens 5

这有几个方面.

语义

预增量(递减)和后递增(递减)的语义是不同的.前者在使用该值之前递增一个值,而后者在使用后递增一个值.例如

unsigned i;
for (i=0; i<10; i++ /* ++i */ ) { } 
Run Code Online (Sandbox Code Playgroud)

在这种情况下,无论是使用前增量还是后增量都无关紧要.这让我想到了第二个方面:

上下文

有时使用前增量或后增量确实很重要,这取决于使用的上下文.请考虑以下示例:

char *p = "some string";
unsigned len = 0;

// test 1
while ('\0' != *p++) { len++; }

// test 2 (assumes that p points to a non-empty string)
while ('\0' != *++p) { ++len; }
Run Code Online (Sandbox Code Playgroud)

结果test 1是字符串的长度,结果test 2是字符串的长度减去1.因为增加的值p被用作表达式的一部分,它确实物质当增量发生的情况:使用后p在表达式(测试1),或之前它的使用(试验2).因为len不使用作为表达式的一部分,它并不重要一个是否使用前或后增量.

这让我想到了第三个方面.

履行

为了实现后增量,p必须将其存储起来以供以后使用以增加它,这会为临时值占用额外的存储空间.预增量不需要临时存储空间.但是,如果递增的值不用作表达式的一部分,那么现代优化编译器能够为前后增量生成相同的代码,其中需要临时值来评估该表达式.

这让我想到了第四个方面(在上一段中略有暗示),但这与C++有关.

性能

在C++中,递减和递增运算符可以被重载(链接)以使用复杂类型,并且STL(链接)确实充分利用它来为其容器类型实现迭代器(链接).在那种情况下,一个值就像

set::iterator it;
Run Code Online (Sandbox Code Playgroud)

可能是一个相当复杂的事情,而不仅仅是一个简单的状态(即它不仅仅是一个原始整数).在这种情况下,使用预增量++it 确实会对后增量产生影响,it++因为如果在表达式中使用(例如上下文),则不需要像临时增量那样存储临时值.这可以节省一些运行时开销.

  • 注意,如果`p`指向一个空字符串,那么测试2(`while('\ 0'!=*++ p){++ len;}`)会失败,因此`*p =='\ 0'`紧接在循环入口之前)因为它跳过null并在未定义的区域中戳. (2认同)