区分字符串和字节数组?

时间:2013-02-02 20:41:35

标签: c string gcc c99 buffer-overflow

我有很多函数希望字符串作为参数,我使用char*,但我所有期望字节数组的函数也使用char*

问题是我很容易犯错误,在字符串函数中传递一个字节数组,导致各种溢出,因为无法找到空终止符。

这通常如何解决?我可以想象将我的所有字节数组函数更改为uint8_t,然后编译器会在传递字符串时发出有关signed-ness的警告。或者这里的正确方法是什么?

4 个答案:

答案 0 :(得分: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 :(得分:1)

C中的问题比你想象的更为普遍。由于char*char[]对于函数参数是等价的,因此这样的参数可以引用三种不同的语义概念:

  • 一个char对象上的指针(这是"官方"指针类型的定义)
  • 一个char数组
  • 一个字符串

在大多数情况下,C标准中的mondern接口使用void*作为无类型字节数组,您应该遵守该约定,并且仅对字符串使用char*。 / p>

char[]本身可能很少使用;我无法想象这些的大量用例。如果您将它们视为数字,则应使用signedunsigned变体,如果您看到它们,则应选择位模式unsigned char

如果您真的将数组表示为函数参数(char或不是),您可以通过清楚地指出代码的随意读者来标记该事实:

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

这相当于

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

但让你的意图更清晰。在未来甚至可能有工具为你做边界检查。

答案 2 :(得分:0)

编写一个通用结构来处理字符串和字节。

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

如果type不是字符串,则仅访问pointer.bufbuf_length。否则直接访问pointer.str而不检查buf_length并将其保持为空终止字符串。

或者通过仅考虑长度来保持字符串也作为字节数组,不要为字符串保留空终止字符。

struct str_or_byte
{
    char *buf;
    int buf_length;
}

并且不要使用不考虑长度的字符串制作功能。这意味着使用strncpystrncatstrncmp ...代替strcpystrcatstrcmp ......

答案 3 :(得分:0)

C使用惯例。这是我使用的规则(在std lib之后制作)

void foo(char* a_string);

void bar(void* a_byte_array, size_t number_of_bytes_in_the_array);   

这很容易记住。如果你传递一个char * ptr,那么它必须是一个以null结尾的char数组。