我在編程時遇到了以下意外行為,我不明白為什么會發生這種情況,或者以下兩種情況之間的區別是什么。
考慮以下兩個代碼片段
#include <stdint.h>
#include <stdio.h>
typedef uint64_t* bitset;
int main(int argc, char ** argv) {
bitset list[2];
list[0] = (uint64_t[2]) {(uint64_t) 0LL, (uint64_t) 0LL};
list[1] = (uint64_t[2]) {(uint64_t) 0LL, (uint64_t) 0LL};
printf("%p\n", &list[0][0]);
printf("%p\n", &list[1][0]);
return 0;
}
和
#include <stdint.h>
#include <stdio.h>
typedef uint64_t* bitset;
int main(int argc, char ** argv) {
bitset list[2];
for(int i = 0; i < 2 ; i ) {
list[i] = (uint64_t[2]) {(uint64_t) 0LL, (uint64_t) 0LL};
}
printf("%p\n", &list[0][0]);
printf("%p\n", &list[1][0]);
return 0;
}
在第一個示例中,兩個值都按預期指向記憶體中的不同位置,但是在通過 for 回圈初始化 list[0] 和 list[1] 時。list[0][0] 和 list[1][0] 都指向記憶體中的相同位置。
是什么導致了這種情況,為什么兩種方法之間的執行存在差異。我在 Ubuntu 機器上編譯,這發生在 gcc 和 clan。
uj5u.com熱心網友回復:
當您撰寫時(uint64_t[2]){0, 0},該運算式稱為“復合文字”,它創建的陣列的范圍是您定義它的塊,因此在您離開塊后,訪問它是無效的。
第一個示例看起來不錯,因為您只是在創建陣列的塊內訪問陣列。您的第二個示例很糟糕(導致未定義的行為),因為復合文字是在回圈迭代內創建的,并且在創建后幾乎立即超出范圍,當程式到達回圈塊的末尾時。
如果它可以幫助您理解:我認為復合文字基本上只是沒有名稱的區域變數。區域變數在其塊結束時超出范圍。
malloc如果您希望它持續更長時間,您可以使用或其他方法分配記憶體。或者不使用指標,只需將bitset自己定義為struct持有兩個數字。然后您的陣列將直接包含您嘗試存盤的資料,而不僅僅是包含指向存盤在其他地方的資料的指標。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/404992.html
標籤:
