在 C 中声明字符串/字符数组的最佳实践是什么?
我有以下样品和评论。
代码#1
如何正确声明以下内容?
char message1[] = "abc"; // will add \0 (null character in the end. so message1 is not equal to message2)
char message2[] = {'a','b','c'}; // tedious to type if you have hundreds of characters to add
C 中的
recv()
套接字函数是否在末尾添加空终止符?
代码#2
如果部分匹配,如何比较 message4 与 message3?
char message3[] = {'a','b','c','e','f'}
char message4[] = {'a','b'}
只是探索和编程新手。
问候
sya
在 C 中,字符串只是字符数组,它们通常以空终止符结尾,允许像
strlen, strcmp, strcpy, etc...
这样的函数对其进行操作。
recv()
不会以空终止符结束缓冲区,而是返回收到的消息的长度,因此,如果您要将此缓冲区作为字符串操作,则应使用有限的函数,例如 strncmp, strncpy, etc...
,其中您可以明确给出数组的大小。
char message1[] = "abc";
或 const char* message1 = "abc";
是定义字符串文字的常用方法。
因此,要比较 message3 和 message4 的第 n 个字符,您可以使用
strncmp
初始化字符数组
如果您打算创建一个以 NUL 结尾的字符串,您应该 always 使用双引号来初始化它,就像在您的
message1[]
中一样。这会自动(隐式)将 NUL 添加为数组中的最后一个字符。
将
char
数组初始化为除 NUL 终止字符串之外的任何内容的情况非常罕见。如果您使用它来存储非字符串数据,您可能会将其声明为 int8_t
或 uint8_t
数组。
不过,也有例外。例如,如果您要创建一个由无符号整数索引的查找表,以将 0...15 范围内的值转换为其十六进制的 ASCII 等效值,则可以使用
message2[]
的格式来实现显然你永远不会将数组用作以 NULL 结尾的字符串。
也就是说,为了简洁起见,大多数开发人员仍然会使用带引号的字符串 (
"0123456789abcdef"
),接受一字节的空间浪费。
recv()
语义
recv()
函数的作用与 read()
类似,因此适用相同的原理。它将准确且仅将其返回的字符数作为其返回值放入提供的缓冲区中。它不添加终端 NUL。
比较固定大小的数组
您不能使用
strlen()
来确定 message3[]
或 message4[]
的长度,因为它们是用大括号定义的,并且不会以 NUL 结尾。您必须假设您将超出数组的末尾!
然而,它们的长度都是预定义的(
char x[] = /*...*/;
而不是char *y = /*...*/;
)这一事实对你有利。您可以对每个值使用 sizeof()
,取两个值的 min()
,然后仅比较该最小长度,从而防止数组溢出。
您应该考虑是否考虑
message3[]
“大于”message4[]
,因为它具有相同的初始子字符串但长度更大,或者您是否认为它们对于您的应用程序目的是相等的。