簡體   English   中英

C - char* 數組的最后一個元素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM