场景
- 我们需要存储常量的字节数组,并且数组里的字节数据可以是任意数值
0-255
。怎么存储?
说明
- 任意字节数组可以使用
char
或者unsigned char
作为数据类型。比如以下的字符串声明。这种字符串数据可以通过strlen(buf)
来计算它的长度,它会遇到\0
结束。常量字符串会自动在末尾增加一个\0
结束符。
const char* buf = "helloworld";
- 如果常量字节数据带了
\0
字符,即0
值,那么这种常量字符串就不适合,因为计算不了它的长度。这时候就可以使用字符数组,如以下的声明。这时候如果buf
的长度可以通过sizeof(buf)
来获取它的大小。但是也因为未预先定义大小的声明方式[]
,字符串初始化在后边自动添加一个\0
字符,所以它的实际大小需要减一,sizeof(buf)-1
. 这种数组声明可以有效的存储任意可见不可见字符,\0
字符等,所以使用它来存储常量字节数据是最合适的。比如某些文件的文件头是固定的常量,我们需要进行比较,就使用字符数组最合适。
char buf[] = "helloworld";
char buf3_1[] = "\xff\x0e\x00\xae";
unsigned char buf4[] = "\xff\x0e\x00\xae";strncmp(buf,buf3_1,4);
- 如果需要存储十六进制字符,可以通过
\x
开头来表示。
例子
- 这里例子说明了
sizeof
和strlen
的使用,并对比了字符数组和常量字符串的计算大小的方式。
#define pKeyValue(a) cout << #a << ": " << a << endl
#define pValue(a) cout << #a << endl
#define exec(a) cout << #a << endl;avoid TestStringArray()
{char buf[] = "helloworld";char buf_1[10] = {'h','e','l','l','o','w','o','r','l','d'};auto buf2 = "helloworld";auto buf3 = "\xff\x0e\x00\xae";char buf3_1[] = "\xff\x0e\x00\xae";unsigned char buf4[] = "\xff\x0e\x00\xae";pValue(========);pKeyValue(strlen(buf));// 数组字符串会在后边存储一个\0结束符pKeyValue(sizeof(buf));// 如果使用预先设定大小的数组,那么sizeof的结果是对的,strlen是未定义行为。// -- 因为数组后边的地址存储的数据不一定是\0结束符。pValue(========);pKeyValue(sizeof(buf_1));pKeyValue(strlen(buf_1));pValue(========);pKeyValue(strlen(buf2));pKeyValue(sizeof(buf2));pKeyValue(strlen(buf3));pValue(========);pKeyValue(strlen(buf3_1));pKeyValue(sizeof(buf3_1));// 有效数据的大小需要减一pKeyValue(sizeof(buf3_1)-1);pValue(========);pKeyValue(sizeof(buf4));}
输出
========
strlen(buf): 10
sizeof(buf): 11
========
sizeof(buf_1): 10
strlen(buf_1): 30
========
strlen(buf2): 10
sizeof(buf2): 4
strlen(buf3): 2
========
strlen(buf3_1): 2
sizeof(buf3_1): 5
sizeof(buf3_1)-1: 4
========
sizeof(buf4): 5
参考
-
关于数组的初始化问题
-
关于使用0初始化结构体的解析