2012-02-28 29 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