[英]C - Last element of char* array
對於以下示例代碼;
char* g_commands[]={
"abcd",
NULL
};
int main()
{
g_commands[1] = "efg";
char ** tmp = &g_commands[0];
for(; *tmp != NULL; tmp++){
printf("%s", *tmp);
}
return 0;
}
由於 tmp 在循環中指向 g_commands 數組中的指針,在我將“efg”分配給 g_commands[1] 之后,我預計循環會創建分段錯誤,因為 g_commands 的最后一個元素不再是 null。 但是程序毫無例外地完成並成功打印 abcdefg。
為什么會這樣? 編譯器是否也將 NULL 添加到 char* 數組的末尾?
我預計循環會產生分段錯誤,因為 g_commands 的最后一個元素不再是 null。 但是程序毫無例外地完成並成功打印 abcdefg。
為什么會這樣? 編譯器是否也將 NULL 添加到 char* 數組的末尾?
當您取消引用指向指向數組末尾的指針tmp
的指針並嘗試使用printf("%s", *tmp)
打印不確定的字符串時,您會調用未定義的行為。
未定義的行為不需要提供錯誤的結果。 當事情看起來正確時,認為事情就是正確的,這是一種誤解。
你不能指望什么。 解釋未定義行為的原因和方式也沒有多大意義,因為它與您編寫生產代碼完全無關。
我知道有些人喜歡研究這些並查看實現的行為,但是如果您對編寫不易受感染、可移植和可靠的代碼感興趣,通常認為這些不是需要更深入地關注的事情。
該程序具有未定義的行為。 特別是它意味着程序可以產生預期或意外的結果。
我希望循環創建分段錯誤,因為 g_commands 的最后一個元素不再是 null
該程序在沒有分段錯誤的情況下工作,因為數組g_commands
char* g_commands[]={
"abcd",
NULL
};
在全局命名空間中定義,並且在數組之后沒有 object 的其他定義。 這樣的聲明具有 static 存儲持續時間,編譯器通常將此 memory 設置為零。
如果您將在 main 中移動定義,例如
#include <stdio.h>
/*
char* g_commands[]={
"abcd",
NULL
};
*/
int main()
{
char* g_commands[]={
"abcd",
NULL
};
g_commands[1] = "efg";
char ** tmp = &g_commands[0];
for(; *tmp != NULL; tmp++){
printf("%s", *tmp);
}
return 0;
}
那么發生分段錯誤的概率非常高。
讓我們一步一步地通過它 go 。
char* g_commands[]={
"abcd",
NULL
};
int main()
{
g_commands[1] = "efg";
此時g_commands
已更改,就好像您已通過以下方式對其進行了初始化:
// char* g_commands[]={
// "abcd",
// "efg"
// };
請注意,從此時起, g_commands
中不再有終止 null 指針。
以下
char ** tmp = &g_commands[0];
也可以寫成
// char ** tmp = g_commands;
現在,當您遍歷g_commands
的元素時,您正在測試對 null 指針的tmp
取消引用。 不幸的是,您之前確實用非空指針覆蓋了g_commands
的最后一個元素,所以這個
for(; *tmp != NULL; tmp++){
printf("%s", *tmp);
}
正在超出數組的范圍並調用未定義的行為。
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.