[英]What is memset doing to a float array?
我最近在網上找到了一段代碼,看起來有點像這樣:
#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]);
}
它產生一個 output 像這樣:
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
重新編譯時值發生變化的地方。
現在我有幾個問題:
float
-array,為什么不能使用char
-array 執行此操作?memset
的值例如1
不會更改 output?為什么 memset 可以比分配的更多寫入
float
-array,為什么不能使用char
-array 執行此操作?
memset(m, 0, 20);
,正如問題最初顯示的那樣,寫入的內容不超過分配的內容。 通常, float
在 C 實現中是四個字節,所以float m[10];
分配 40 個字節和memset(m, 0, 20);
寫 20。
在新代碼中, memset(m, 0, sizeof m);
向m
寫入盡可能多的字節,不多也不少。
如果要求memset
寫更多,您可以嘗試這樣做的原因是 C 實現通常不進行安全檢查操作,而 C 標准不要求它們這樣做。
為什么如此不一致?
沒有什么不一致的。 memset
將零寫入m
的前 20 個字節,這是浮點零的編碼,采用float
常用的格式(IEEE-754 binary32,也稱為“單精度”)。
之后的字節沒有被寫入,因此打印它們使用未初始化的數據。 C 標准說未初始化對象的值是不確定的。 一個常見的結果是程序已經使用了 memory 中的任何內容。 那可能是零,也可能是其他東西。
但是, for (int i = 0; i < 20; i++)
的循環,您 go 超出了m
中的 10 個元素。 那么訪問m[i]
的行為不是由 C 標准定義的。 如上所述,一個常見的結果是程序訪問計算的 memory 並使用發生的任何內容。 但是,其他各種行為也是可能的,包括由於嘗試訪問未映射的 memory 或編譯器在優化期間用替代代碼替換未定義代碼而導致的崩潰。
為什么更改
memset
的第二個值不會更改 output?
它將取決於您將其更改為什么。 字節的某些值可能會導致float
值非常小,它們仍然打印為“0.000000”。 例如,如果將字節設置為 1,使每個float
中的 32 位0x01010101
,它們表示float
值2.36942782761723955384693006253917004604239556833255136345174597127722672385008451101850084511018181850084511018181818
如果您使用 64 作為memset
的第二個參數,則這些位將設置為0x40404040
,它對值 3.0039215087890625 進行編碼,因此將打印“3.003922”。
Memset
對float
組沒有任何作用。 您只有一個包含 10 個浮點數的數組,並且您使用了一個覆蓋 20 個浮點數的循環,這意味着,由於 C 不檢查數組邊界……您已經從數組的末尾擴展了很遠,並將其解釋為浮點數不是。 我不會在這里重復其他答案中已經說過的內容,但是您在調整 C 對象的大小時遇到了問題。 sizeof
運算符是您的朋友。 在將 arguments 傳遞給memcpy
或malloc
等函數時使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.