2012-02-28 35 views
2

我翻遍了一堆问题,看不到这个,尽管我确定它已经在某个地方了。所以我很抱歉,并认为这将会结束,但希望有人会首先确认我的答案!C++未定义行为还是不行? (再次)

我是在想,纠正:

while (--len > -1 && ptr = str[len]) 

被很好地定义(没有未定义!)的行为吗?我理解的方式是,& &是一个序列点,短路的方式将起作用,这意味着--len > -1应该首先评估,如果它不安全,则不会发生第二部分。

虽然我不确定自己在这个思维过程中是否正确。

+0

取决于此语句之前len的值是多少。如果它是0或更大,该怎么办?那么将评估ptr = str [len]。 – Sid 2012-02-28 17:20:23

+0

是的,好点。这在我的情况下并不危险,但我并没有首先考虑它是不好的。 :) – 2012-02-28 17:24:06

回答

5

这被定义行为&&是一个sequence point和你理解它的方式是正确的。从链接的维基百科页面:

在C [2]和C++,[3]顺序点发生在以下位置:

的& &的左边和右边的操作数的评价(逻辑之间),|| (逻辑OR)和逗号运算符。例如,在表达式* p ++!= 0 & & * q ++!= 0中,子表达式* p ++!= 0的所有副作用在任何尝试访问q之前完成。

但是,这并不确保--len不会导致索引超出str的范围。如果str是一个空结束的str你可以改变:

while (--len > -1 && len < strlen(str) && ptr = str[len]) 
+0

非常感谢:) – 2012-02-28 18:16:23

+0

@hmjd:我会避免在循环的每次运行时重新计算'strlen',它肯定是浪费。如果'len'不如'strlen(str)'开头,那么递减它不应该改变这个事实。当然,这个假设'str'本身不移动,在这里看起来就是这种情况。 – 2012-02-28 18:16:50

1

是的,这是正确的。顺序为:

  1. len递减
  2. (新值)len如果(2)评估以真相比-1
  3. ptr = str[len]
+0

感谢您的快速回答;) – 2012-02-28 19:35:50

0

您是认为ptr = str[len]不执行,如果--len > -1是假的权利(这可能是一个未定义的行为是len为过大的索引数组,我认为这不是你所害怕的)。如果len事先是INT_MIN,则--len可能是一个未定义的行为(如果len被初始化,则不会很有可能),因为有符号算术的溢出是未定义的行为。

0
while (--len > -1 && ptr = str[len]) 
例如用于LEN = 1

(如果len为INT)的东西是这样认为:

1) len = len-1=0 
2) ptr = str[0] 

2)是因为,如果LEN的递减的if语句的第一部分。 是你想要的吗?

但是行为是被定义的,第一部分将被首先检查。

0

这实际上是确定的。这里的关键是你不会多次写入len

首先你先递减len。然后检查减量值len是否至少为0.接下来,将str[len](使用递减的len)分配到ptr。最后检查ptr是否为非空,如果是,则执行while循环语句。

请注意,如果len未签名,则-1将被提升为无符号,并且该循环几乎肯定会使第一次迭代失败。此外,即使len如果具有未指定的最小int值(std::numeric_limits<int>::min())递减,也会被签名。

+0

*这里的关键是你不会多次写入len。*这不一定是问题。 'map [++ i] = i'只写入'i'一次,但尚未定义。 – 2012-02-28 18:18:03