[C] 每天來點字串用法 (2) - strcpy()、strncpy()

結果隔了四天(不要相信 blogger 自帶的時間(?))才更新qwq,前幾天根本忘得一乾二淨XD
進入正文吧,今天要介紹的是:
  • strcpy()、strncpy():字串複製
  所屬標頭檔:<string.h>
  函式宣告:
char *strcpy( char *dest, const char *src );
char *strncpy( char *dest, const char *src, size_t count );
  先說 strcpy(),將來源字串 (src) 複製到目的地 (dest),並回傳 dest 指向的字串,要注意的有以下兩點:
          1) 第一個參數是目的地 (dest),第二個是來源 (src)
          2) 會有緩衝區溢位 (buffer overflow) 的問題

  來看看何謂緩衝區溢位:假設有一程式進行了如下宣告:
int i = 5;
char s[8] = "Hi 1234";
  那麼這些變數的記憶體配置可能如下:
  如果今天我們進行了如下操作:
strcpy(s, "hello sky");
  那麼記憶體裡的內容就會變成如下:
  於是這時 i 的值就會變成 121,我們可以用以下程式來驗證:
#include <stdio.h>
#include <string.h>

int main(void){
    int i = 5;
    char s[8] = "Hi 1234";
    printf("address of i: %p\naddress of s: %p\n", &i, s);  // i: 0028ff1c, s: 0028ff14
    strcpy(s, "hello sky");
    printf("value of s: %s\nvalue of i: %d\n", s, i);  // s: hello sky, : 121

    return 0;
}

  為了解決這樣的問題,我們可以改用 strncpy(),他比 strcpy() 多了一個參數:count,用來控制最多複製幾個字元,而它一樣會回傳 dest 指向的字串。這裡也有些地方要注意:
          1) 如果 src 字元數(含 '\0')比 count 少,會把剩下未滿 count 的部分通通補上 '\0'
          2) 如果 src 字元數(含 '\0')比 count 多,他不會幫你補 '\0',而是要自己補
  strncpy() 的使用可參考以下範例:
#include <stdio.h>
#include <string.h>

int main(void){
    int i = 67;  // ASCII 的 'C'
    char s[8] = "Hi 1234";
    printf("address of i: %p\naddress of s: %p\n", &i, s);
    strncpy(s, "hello sky", 8);
    printf("(1) value of s: %s\nvalue of i: %d\n", s, i);  // s: hello skC, i: 67
    s[7] = '\0';  // 自己補 '\0'
    printf("(2) value of s: %s\n", s);  //  s: hello s

    return 0;
}


  • Undefined Behavior
  在使用這兩個函式時,可能會造成 undefined behavior,以下列舉可能的情況:
    • strcpy()
          1) 緩衝區溢位  ※ 其實是 dest 不夠長
          2) dest 和 src 有重疊的部分*
          3) 如果 dest 指到的不是一個字元陣列
          4) 如果 src 指向的字串沒有以 '\0' 結尾
    • strncpy()
          1) dest 和 src 有重疊的部分*
          2) 如果 dest 或 src 其中一個不是指向一個字串
          3) 如果 dest 不夠長(比 count 短)
          4) 如果 src 比 count 短而且 src 沒有以 '\0' 結尾

其實這個部分在 C99 已受到限制:宣告中新增了 restrict 關鍵字,關於這個關鍵字有興趣的人可以自己查查看

天啊不是我在說,blogger 首頁的文章預覽圖也太醜了吧qq,而且是發佈後才知道ˊˇˋ
希望我可以堅持下去。(已對自己無信心

參考資料:
  1) cppreference - strcpy
  2) cppreference - strncpy
  3) 我休息了4天的腦袋

留言

這個網誌中的熱門文章

[Python] *args 和 **kwargs 是什麼?一次搞懂它們!

[C] 每天來點字串用法 (5) - strcat()、strncat()