![](/img/trans.png)
[英]Why does initializing a sigint variable with memset() help prevent Seg Faults?
[英]Why is memset() incorrectly initializing int?
為什么以下程序的輸出是84215045
?
int grid[110];
int main()
{
memset(grid, 5, 100 * sizeof(int));
printf("%d", grid[0]);
return 0;
}
memset
將目標緩沖區的每個字節設置為指定值。 在您的系統上,一個int
是四個字節,在調用memset
之后每個字節是 5。 因此, grid[0]
的值為0x05050505
(十六進制),即十進制的84215045
。
一些平台為memset
提供了替代 API,可以將更廣泛的模式寫入目標緩沖區; 例如,在 OS X 或 iOS 上,您可以使用:
int pattern = 5;
memset_pattern4(grid, &pattern, sizeof grid);
獲得您似乎期望的行為。 你的目標是什么平台?
在 C++ 中,您應該只使用std::fill_n
:
std::fill_n(grid, 100, 5);
memset(grid, 5, 100 * sizeof(int));
您正在設置 400 個字節,從(char*)grid
開始,到(char*)grid + (100 * sizeof(int))
結束,到值5
(這里需要強制轉換,因為memset
處理字節,而指針算術交易objects
。
十六進制的84215045
是0x05050505
; 由於int
(在您的平台/編譯器/等上)由四個字節表示,因此當您打印它時,您會得到“四個五”。
memset
是關於設置字節,而不是值。 在 C++ 中設置數組值的眾多方法之一是std::fill_n
:
std::fill_n(grid, 100, 5);
不要使用 memset。
您將內存的每個字節[]
設置為 5。每個 int 的長度為 4 個字節[5][5][5][5]
,編譯器將其正確解釋為 5*256*256*256 + 5* 256*256 + 5*256 + 5 = 84215045。相反,使用 for 循環,它也不需要 sizeof()。 一般來說, sizeof() 意味着你正在做一些艱難的事情。
for(int i=0; i<110; ++i)
grid[i] = 5;
好吧, memset
使用選定的值寫入字節。 因此 int 看起來像這樣:
00000101 00000101 00000101 00000101
然后將其解釋為 84215045。
你實際上並沒有說你想讓你的程序做什么。
假設您要將grid
的前 100 個元素中的每一個設置為 5(並忽略100
與110
的差異),只需執行以下操作:
for (int i = 0; i < 100; i ++) {
grid[i] = 5;
}
我了解您擔心速度,但您的擔心可能是錯誤的。 一方面, memset()
可能會被優化,因此比簡單的循環更快。 另一方面,優化可能包括一次寫入多個字節,這就是這個循環所做的。 另一方面, memset()
無論如何都是一個循環; 顯式編寫循環而不是將其埋在函數調用中並不會改變這一點。 另一方面,即使循環很慢,也可能無關緊要。 專注於編寫清晰的代碼,如果實際測量表明存在嚴重的性能問題,則考慮對其進行優化。
您編寫問題所花費的時間比您的計算機設置grid
所花費的時間要多很多數量級。
最后,在我手忙腳亂(為時已晚!)之前,如果memset()
不能滿足您的要求,那么它的速度並不重要。 (根本不設置grid
甚至更快!)
如果你在 shell 上輸入man memset
,它會告訴你
void * memset(void *b, int c, size_t len)
一個簡單的英語解釋是,它填充一個長度為len
的字節串b
,每個字節都有一個值c
。
對於你的情況,
memset(grid, 5, 100 * sizeof(int));
由於sizeof(int)==4
,因此上面的代碼片段看起來像:
for (int i=0; i<100; i++)
grid[i]=0x05050505;
或者
char *grid2 = (char*)grid;
for (int i=0; i<100*sizeof(int); i++)
grid2[i]=0x05;
它將打印出84215045
但在大多數 C 代碼中,我們希望將一塊內存塊初始化為零。
char
類型 --> \\0
或NUL
int
類型 --> 0
float
類型 --> 0.0f
double
類型 --> 0.0
nullptr
gcc或clang等現代編譯器可以自動為您處理好這個問題。
// variadic length array (VLA) introduced in C99
int len = 20;
char carr[len];
int iarr[len];
float farr[len];
double darr[len];
memset(carr, 0, sizeof(char)*len);
memset(iarr, 0, sizeof(int)*len);
memset(farr, 0, sizeof(float)*len);
memset(darr, 0, sizeof(double)*len);
for (int i=0; i<len; i++)
{
printf("%2d: %c\n", i, carr[i]);
printf("%2d: %i\n", i, iarr[i]);
printf("%2d: %f\n", i, farr[i]);
printf("%2d: %lf\n", i, darr[i]);
}
但請注意,C ISO 委員會並沒有強加這樣的定義,它是特定於編譯器的。
此代碼已經過測試。 這是一種將“整數”數組設置為 0 到 255 之間的值的方法。
MinColCost=new unsigned char[(Len+1) * sizeof(int)];
memset(MinColCost,0x5,(Len+1)*sizeof(int));
memset(MinColCost,0xff,(Len+1)*sizeof(int));
由於 memset 寫入字節,我通常使用它將一個 int 數組設置為零,例如:
int a[100];
memset(a,0,sizeof(a));
或者您可以使用它來設置 char 數組,因為 char 正是一個字節:
char a[100];
memset(a,'*',sizeof(a));
更重要的是,一個 int 數組也可以通過 memset 設置為 -1:
memset(a,-1,sizeof(a));
這是因為 -1 在 int 中是 0xffffffff,在 char(一個字節)中是 0xff。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.