将新字符串值分配给 char 数组的最佳方法
best method to assign new string value to char array
我知道我必须使用 strcpy / strncpy 将新的字符串值分配给现有的 char 数组。最近看到很多这样的代码
char arr[128] = "[=10=]";
sprintf(arr, "Hello World"); // only string constants no variable input
// or
sprintf(arr, "%s", "Hello World");
两种变体给出相同的结果。后一种变体的优点是什么?
如果字符串包含任何 %
个字符,第一个版本将不起作用,因为 sprintf()
会将它们视为需要使用其他参数填充的格式化运算符。这不是'像 Hello World
这样的固定字符串没有问题,但是如果您动态获取字符串,它可能会导致未定义的行为,因为不会有任何参数来匹配格式化运算符。这可能会导致安全漏洞。
如果您实际上没有进行任何格式化,更好的方法是只使用 strcpy()
:
strcpy(arr, "Hello World");
此外,在初始化字符串时,不必在字符串中显式放置 [=16=]
。字符串文字总是以空字节结尾。所以你可以将它初始化为:
char arr[128] = "";
如果您立即用 sprintf()
或 strcpy()
覆盖变量,则无需首先对其进行初始化。
这取决于要复制的字符串是否是文字,如图所示,或者可以变化。
所示阵列的最佳技术是:
char arr[128] = "Hello World";
如果您负责字符串并且它不包含 %
符号,那么这两个 sprintf()
调用之间没有太大区别。严格来说,第一个使用字符串作为格式并直接复制字符,而第二个注意它具有 %s
作为格式并直接从额外参数复制字符——它慢得无法估量。有一个案例:
snprintf(arr, sizeof(arr), "%s", "Hello World");
即使 "Hello World" 变得更长的谩骂也能确保缓冲区不会溢出。
如果您不负责字符串,那么使用 snprintf()
变得很重要,因为即使字符串包含 %
符号,它也只是被复制并且没有溢出。您必须检查 return 值以确定是否有任何数据被截断。
如果您知道字符串的长度并且有 space 来保存它,那么使用 strcpy()
是合理的。使用 strncpy()
很麻烦——如果源比目标短,它会空填充到全长,如果源对于目标来说太长,它不会空终止。
如果您确定字符串的长度足够短,使用 memmove()
或 memcpy()
也是合理的。如果字符串太长,则必须选择一种错误处理策略——截断或错误。
如果目标数组中的尾随(未使用)space 必须为空字节(出于安全原因,以确保其中没有隐藏剩余的密码),那么使用 strncpy()
可能是明智的— 但要注意确保如果源代码太长则空终止。在大多数情况下,实际上并不需要数组的初始化程序。
编译器也许能够优化简单的情况。
我知道我必须使用 strcpy / strncpy 将新的字符串值分配给现有的 char 数组。最近看到很多这样的代码
char arr[128] = "[=10=]";
sprintf(arr, "Hello World"); // only string constants no variable input
// or
sprintf(arr, "%s", "Hello World");
两种变体给出相同的结果。后一种变体的优点是什么?
如果字符串包含任何 %
个字符,第一个版本将不起作用,因为 sprintf()
会将它们视为需要使用其他参数填充的格式化运算符。这不是'像 Hello World
这样的固定字符串没有问题,但是如果您动态获取字符串,它可能会导致未定义的行为,因为不会有任何参数来匹配格式化运算符。这可能会导致安全漏洞。
如果您实际上没有进行任何格式化,更好的方法是只使用 strcpy()
:
strcpy(arr, "Hello World");
此外,在初始化字符串时,不必在字符串中显式放置 [=16=]
。字符串文字总是以空字节结尾。所以你可以将它初始化为:
char arr[128] = "";
如果您立即用 sprintf()
或 strcpy()
覆盖变量,则无需首先对其进行初始化。
这取决于要复制的字符串是否是文字,如图所示,或者可以变化。
所示阵列的最佳技术是:
char arr[128] = "Hello World";
如果您负责字符串并且它不包含 %
符号,那么这两个 sprintf()
调用之间没有太大区别。严格来说,第一个使用字符串作为格式并直接复制字符,而第二个注意它具有 %s
作为格式并直接从额外参数复制字符——它慢得无法估量。有一个案例:
snprintf(arr, sizeof(arr), "%s", "Hello World");
即使 "Hello World" 变得更长的谩骂也能确保缓冲区不会溢出。
如果您不负责字符串,那么使用 snprintf()
变得很重要,因为即使字符串包含 %
符号,它也只是被复制并且没有溢出。您必须检查 return 值以确定是否有任何数据被截断。
如果您知道字符串的长度并且有 space 来保存它,那么使用 strcpy()
是合理的。使用 strncpy()
很麻烦——如果源比目标短,它会空填充到全长,如果源对于目标来说太长,它不会空终止。
如果您确定字符串的长度足够短,使用 memmove()
或 memcpy()
也是合理的。如果字符串太长,则必须选择一种错误处理策略——截断或错误。
如果目标数组中的尾随(未使用)space 必须为空字节(出于安全原因,以确保其中没有隐藏剩余的密码),那么使用 strncpy()
可能是明智的— 但要注意确保如果源代码太长则空终止。在大多数情况下,实际上并不需要数组的初始化程序。
编译器也许能够优化简单的情况。