我最近在網上找到了一段代碼,看起來有點像這樣:
#include <stdio.h>
#include <string.h>
int main() {
float m[10];
memset(m, 0, 20);
}
我還看到了一個片段,我認為它是正確的:
memset(m, 0, sizeof m);
嘗試使用此代碼段列印出第一個示例的所有值時:
for (int i = 0; i < 20; i ) {
printf("%f, \n", m[i]);
}
它產生這樣的輸出:
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
-0.000000,
-4587372491414098149376.000000,
-0.000013,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000,
0.000000
重新編譯時值發生變化的地方。
現在我有幾個問題:
- 為什么 memset 寫入
float-array 的次數比分配的要多,為什么不能用char-array做到這一點? - 為什么如此不一致?
- 為什么改變第二值,值
memset到1例如不改變輸出?
uj5u.com熱心網友回復:
為什么 memset 寫入
float-array 的次數比分配的要多,為什么不能用char-array做到這一點?
memset(m, 0, 20);,正如最初的問題所示,寫入的內容不會超過分配的內容。通常,float在 C 實作中是 4 個位元組,因此float m[10];分配 40 個位元組,并memset(m, 0, 20);寫入 20 個。
在新代碼中,memset(m, 0, sizeof m);寫入盡可能多的位元組m,不多也不少。
如果memset被要求撰寫更多,您可以嘗試這樣做的原因是 C 實作通常不進行安全檢查操作,而 C 標準不要求它們這樣做。
為什么如此不一致?
沒有任何不一致的地方。memset將 0 寫入 的前 20 個位元組m,這是浮點零的編碼,采用常用的格式float(IEEE-754 binary32,也稱為“單精度”)。
之后的位元組未被寫入,因此列印它們使用未初始化的資料。C 標準說未初始化物件的值是不確定的。一個常見的結果是程式使用了記憶體中已經存在的任何內容。那可能是零,也可能是別的東西。
但是,使用 loop for (int i = 0; i < 20; i ),您超出了 中的 10 個元素m。那么訪問的行為m[i]不是由C標準定義的。如上所述,一個常見的結果是程式訪問計算出的記憶體并使用那里發生的任何事情。然而,各種其他行為也是可能的,包括由于嘗試訪問未映射記憶體或編譯器在優化期間用替代代碼替換未定義代碼而導致的崩潰。
為什么改變第二個值
memset不會改變輸出?
它將,取決于您將其更改為什么。位元組的某些值可能會導致float值太小,它們仍會列印為“0.000000”。例如,如果位元組被設定為1,使得32位0x01010101中的每個float,所以它們代表了float的2.36942782761723955384693006253917004604239556833255136345174597127722672385008451101384707726538181?10值-38。
如果您使用 64 作為 的第二個引數memset,則位將設定為0x40404040,對值 3.0039215087890625 進行編碼,因此將列印“3.003922”。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/364679.html
