我正在運行這個 C 程式:
#include<stdio.h>
void print(int* a, int* b, int* c, int* d, int* e)
{
printf("%d %d %d %d %d\n", *a, *b, *c, *d, *e);
}
int main()
{
static int a[] = {97, 98, 99, 100, 101, 102};
int* ptr = a 1;
print( ptr, ptr--, ptr, ptr , ptr);
ptr = a 1;
printf("%d %d %d %d %d\n", * ptr, *ptr--, *ptr, *ptr , * ptr);
int i = 0;
printf("%d %d %d", i , i, i);
}
一個編譯器將其列印為輸出:
99 99 98 98 100
99 99 98 98 100
0 2 3
另一個編譯器列印:
100 100 100 99 100
100 100 100 99 99
2 3 3
現在,我對正在發生的事情感到困惑。正確的順序是什么?
uj5u.com熱心網友回復:
函式呼叫的評估在 2018 版 C 標準條款 6.5.2.2 中指定,但該條款未指定引數評估的順序。任何訂單都是允許的。
因此,print( ptr, ptr--, ptr, ptr , ptr);C 標準沒有定義 的行為。6.5 2 說:
如果標量物件上的副作用相對于同一標量物件上的不同副作用或使用相同標量物件的值的值計算是未排序的,則行為未定義。如果運算式的子運算式有多個允許的排序,則如果在任何排序中出現這種未排序的副作用,則行為未定義。
ptr是一個標量物件。(C 2018 6.2.5 21 說“算術型別和指標型別統稱為標量型別。”) ptr并通過副作用進行ptr--更改。ptr( 的“主要”效果 ptr是計算 的增量值ptr。它的副作用是更新 的存盤值ptr。)由于這些副作用沒有排序,因此滿足 6.5 2 的條件,因此適用,并且行為不是由 C 標準定義的。
請注意,這不僅意味著ptr可以按照編譯器碰巧選擇的任何順序進行更新。當 C 標準說行為未定義時,這意味著它根本沒有對行為施加任何要求。對物件的兩次更新可能會發生沖突,以不同的順序更新它的不同位元組,產生一個無法通過以任何順序單獨連續更新獲得的值。(例如,當編譯器使用原始機器中的兩位元組更新實作四位元組指標時,可能會發生這種情況。)或者編譯器中的優化器可以識別代碼沒有定義的行為并將其從程式中完全洗掉,或者用其他代碼替換它。(例如,如果程式在兩個代碼序列之間包含一個分支,并且優化器識別出一個分支在特定情況下會具有未定義的行為,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/438320.html
