为什么要我++;一世 - ; 彼此对吗?


164

我查看的是1997年发布的nmap的源代码,我注意到这段代码对我来说有点奇怪:

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
ports = safe_malloc(65536 * sizeof(short));
i++;                                         /* <<<<<< */
i--;                                         /* <<<<<< */
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

为什么你们会彼此i++;紧接着i--;又互相拥有?i0,则i++轮流i1。在那之后,i--变成i0

链接到原始源代码。搜索:

i++;
i--;

谁能解释这是什么意思?


25
询问作者
达伯勒

8
我想它们是一些实验或调试代码的一部分,作者后来忘了删除它们。
Nate Eldredge

6
原因显然是使您感到困惑,这是唯一的目的:-)这很少有机会解决某些古老的编译器中的某些编译器错误,在这种情况下,应该有注释告诉我们这个原因。
gnasher729

18
@RingØ:有趣的是,我在1988年左右的gcc 1.27上在godbolt上进行了尝试:godbolt.org/z/yYyFrQ。(它不适用于现代系统头文件,因此我必须自己声明所有标准库函数。)但是,-O确实可以优化这些语句。
Nate Eldredge

21
这意味着程序员是按行支付的……
TonyK,

Answers:


152

这是一个错误。这些行导致i未更改,因此不应该在那里。

引入nmap的链接文章于1997年9月1日发布。如果您在https://svn.nmap.org/nmap上查看nmap的SVN存储库,则在1998年2月10日签入的初始修订没有这些行:

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
char *mem = expr;

ports = safe_malloc(65536 * sizeof(short));
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

因此,这是作者发现的问题,并且已在发布初始nmap源代码和初始检入到SVN之间进行了修复。


1
那个页面也缺少<pre>文章周围的标签;Chrome浏览器的检查器揭示了这如何导致DOM构建期间的某些文档处理;)
带翼的小行星

4
它使读者感到困惑,这完全是意料之外的。我想说这显然是一个错误。;-)
sergut

2
@sergut维基百科不同意您的观点,但此博客文章也同意,我也很
乐意

4
现在,如果i不是int而是一些带有运算符重载的特殊类,则可能(尽管不太可能,并且通常是不良的编码实践的迹象)可能会产生一些副作用。(仅适用于当然是C ++的情况。)
Darrel Hoffman

5
可能值得注意的是,在某些情况下(内存映射的IO),更改变量会产生外部影响。
nullromo

40

没用的。它绝对没有任何作用。

如果我推测这可能是开发过程中使用的一些调试代码的剩余部分。

我猜的任何一个i++i--一个进行了更改,另一个是在其他介绍。

但是,我没有办法找到介绍的重点,因为在初始源版本和第一个SVN版本之间没有修订历史记录。


14
我认为有关调试代码的猜测是正确的。我已经看到了许多不同类型的调试代码,只是为了在您期望的地方获得断点。
森·高斯

9

对于非优化的编译器或识别出硬件副作用的编译器,i ++; i--序列将导致从内存中读取i,然后将其重新写入,而不管通过for循环并嵌套if的路径如何。

在并行处理中,有时会采用编译器技巧来确保代码序列使用其自己的变量本地副本而不是全局副本。

由于该示例是一个代码段,因此无法确定所使用的编译器,所需的操作系统/硬件,也无法确定其是否处于可以作为独立线程执行的代码序列/功能中。

在较简单的系统中,我暂时强制更改变量以在调试环境中使用陷阱功能。如果是这样,开发人员可能忘了在开发完成后删除代码。


1
那为什么不仅仅声明它为volatile呢?
vsz

6
i作为局部变量的声明如上面的代码所示,并且在行所在的位置,其他线程无法访问它i++; i--
Interjay

@vsz我宁愿认为他的意思i是被迫保持不变。我没有处理C或C ++中的线程,因此我不知道如何将其视为易失性以及如何i++; i--抑制这种情况。
Egor Hans

volatile除了线程安全性还有其他目的。它还可以在调试时使用,以确保编译器不会对其进行优化。
vsz

2

我建议您仅检查更新的代码。如果紧接在(i-1)之后使用(i = 2 + 1),则没有任何意义。i的值保持不变。您可以使用任何c或c ++编译器进行尝试。甚至其他任何语言都一样。在编译器中运行代码,看看我是对还是错,然后让我知道我给出的答案是否正确。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.