2013-02-02 120 views
6

我有很多函數需要一個字符串作爲參數,爲此我使用char*,但是所有期望字節數組的函數也使用char*區分字符串和字節數組?

問題是我可以很容易地在字符串函數中傳遞一個字節數組,導致各種溢出錯誤,因爲無法找到null終止符。

這是怎麼回事?我可以想象將所有的字節數組函數改爲uint8_t,然後當我傳遞一個字符串時,編譯器會警告有關簽名的問題。或者這裏的正確方法是什麼?

+0

爲字節數組做一個包裝? –

+0

@VaughanHilts我不明白這是如何解決我的問題? – Muis

+0

一個字符串*是一個字節數組。既然你實際上不能在C中傳遞數組,但只有一個指向第一個元素的指針,你通常也必須傳遞一個大小。只需檢查數組是否包含零值。如果是這樣,那麼它是一個「字符串」。否則,它不是。 –

回答

1

的問題在C更普遍比你所想。由於char*char[]是等價爲函數的參數,這種參數可以是指三個不同的語義概念:

  • 一個char對象的指針(這是指針類型的「正式」的定義)
  • 一個char陣列
  • 字符串

在是大多數情況下是可能的C標準的mondern接口使用void*爲無類型字節AR ray,而且你應該遵守該慣例,並且僅對字符串使用char*

char[]本身可能很少使用,我無法想象這些用例很多。如果你認爲它們是數字,你應該使用signedunsigned變體,如果你看到它們,就像你應該選擇位模式unsigned char一樣。

如果你真的是一個數組作爲函數的參數(char與否)你可以清楚地表明它標誌着這一事實對你的代碼的普通讀者:

void toto(size_t n, char A[const n]); 

這相當於

void toto(size_t n, char *const A); 

但讓你的意圖更清晰。而且在未來,甚至可能會有工具來檢查你的邊界。

2

我一般做一個數組像下面

typedef struct { 
    unsigned char* data; 
    unsigned long length; 
    unsigned long max_length; 
} array_t; 

然後通過array_t *各地

,並創建採取array_t *

void array_create(array_t* a, unsgined long length) // allocates memory, sets the max_length, zero length 

void array_add(array_t* a, unsigned char byte) // add a byte 

+1

可能會更好地使用'size_t'而不是'unsigned long' –

+0

是的,你是對的 –

0

寫入陣列功能一個處理字符串和字節的通用結構。

struct str_or_byte 
{ 
    int type; 
    union 
    { 
     char *buf; 
     char *str; 
    }pointer; 
    int buf_length; 
} 

如果type不是字符串,則訪問pointer.buf只有高達buf_length。否則直接訪問pointer.str而不檢查buf_length並將其保留爲空字符結束。

或者,通過僅考慮長度來維護字符串也作爲字節數組,不要將空字符串保留爲空字符串。

struct str_or_byte 
{ 
    char *buf; 
    int buf_length; 
} 

而且不使用不考慮長度的字符串manuplation函數。這意味着使用strncpystrncatstrncmp ...而不是strcpystrcatstrcmp ...

0

C使用約定。這裏是我使用的規則(在標準庫之後製作)

void foo(char* a_string); 

void bar(void* a_byte_array, size_t number_of_bytes_in_the_array); 

這很容易記住。如果你傳遞一個char * ptr,那麼它必須是一個以null結尾的char數組。