snprintf/sprintf 是否会覆盖倒数第二个参数的终止空值,就像 strcat 一样?
Does snprintf/sprintf overwrite the terminating-null of the penultimate argument, just like strcat does?
显然是为strcat
写的,例如here and here 以防万一,
char *strcat(char *s1, const char *s2);
然后,
The initial character of s2 overwrites the null character at the end of s1.
但显然在这里搜索了一些“在 C 中连接 strings/literals”,我偶然发现了 this,其中指出,
Avoid using strcat in C code. The cleanest and, most importantly, the safest way is to use snprintf:
那么,对于 snprintf/sprintf
来说, 下一个参数的第一个字符覆盖前一个参数的空终止符 也是如此吗?我在 documentation.
中看不到这样的引用
经验证据似乎表明,strcat 和 snprintf 的行为方式相同。还是我的假设错了?
#include <string.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf( "Test Program Started\n");
const char* first = "a";
const char* second = "b";
const char* third = "c";
const int merged_length = (strlen(first) + strlen(second) + strlen(third) + 1); // +1 for null-termination
char* catResult;
catResult = malloc( merged_length * sizeof(char));
strcpy(catResult, first);
strcat(catResult, second);
strcat(catResult, third);
catResult[merged_length] = '[=12=]';
printf("catResult:%s \tstrlen(catResult):%d \t sizeof(catResult):%d\n",
catResult,
strlen(catResult),
sizeof(catResult));
free(catResult);
char* snprintfResult;
snprintfResult = malloc( merged_length * sizeof(char));
snprintf(snprintfResult, merged_length, "%s%s%s", first, second, third);
// catResult[merged_length] = '[=12=]'; // not necessary as per documentation
printf("snprintfResult:%s \tstrlen(snprintfResult):%d \tsizeof(snprintfResult):%d\n",
snprintfResult,
strlen(snprintfResult),
sizeof(snprintfResult));
free(snprintfResult);
}
Test Program Started
catResult:abc strlen(catResult):3 sizeof(catResult):4
snprintfResult:abc strlen(snprintfResult):3 sizeof(snprintfResult):4
snprintf
和 sprintf
不像 strcat
那样附加到先前的字符串。他们在传递给他们的缓冲区的开头开始写入。
在一次调用中写入多个字符串时,与格式字符串"%s%s%s"
一样,它们将连续写入字符串,它们之间没有空字符,并以空字符结尾。
如果您希望它们附加到名为 buffer
的缓冲区中的现有字符串,则确定字符串的长度,例如 n
,并将 buffer + n
作为第一个传递参数而不是 buffer
。 (对于 snprintf
,请注意还应从第二个参数中减去 n
,该参数指定缓冲区中可用的字节数。)
你不能那样使用 sizeof
。虽然 sizeof("string")
如您所愿,但 sizeof(string pointer)
在任何给定平台上总是 returns 相同的值(通常为 4 或 8)。
const int merged_length = (sizeof(first) + sizeof(second) + sizeof(third) + 1);
应该是
const int merged_length = (strlen(first) + strlen(second) + strlen(third) + 1);
当您将 %s
写入 snprintf
时,它会将字符串复制到目标字符串,不带任何尾随空值。当到达格式字符串末尾的 null 终止符时,输出字符串也以 null 终止。
所以,你的问题的实际答案是否定的,因为null在first
之后从来没有写过,但最终的效果更像是我们回答是的,因为这两个代码片段做同样的事情.
显然是为strcat
写的,例如here and here 以防万一,
char *strcat(char *s1, const char *s2);
然后,
The initial character of s2 overwrites the null character at the end of s1.
但显然在这里搜索了一些“在 C 中连接 strings/literals”,我偶然发现了 this,其中指出,
Avoid using strcat in C code. The cleanest and, most importantly, the safest way is to use snprintf:
那么,对于 snprintf/sprintf
来说, 下一个参数的第一个字符覆盖前一个参数的空终止符 也是如此吗?我在 documentation.
经验证据似乎表明,strcat 和 snprintf 的行为方式相同。还是我的假设错了?
#include <string.h>
#include <stdio.h>
int main(int argc, char const *argv[])
{
printf( "Test Program Started\n");
const char* first = "a";
const char* second = "b";
const char* third = "c";
const int merged_length = (strlen(first) + strlen(second) + strlen(third) + 1); // +1 for null-termination
char* catResult;
catResult = malloc( merged_length * sizeof(char));
strcpy(catResult, first);
strcat(catResult, second);
strcat(catResult, third);
catResult[merged_length] = '[=12=]';
printf("catResult:%s \tstrlen(catResult):%d \t sizeof(catResult):%d\n",
catResult,
strlen(catResult),
sizeof(catResult));
free(catResult);
char* snprintfResult;
snprintfResult = malloc( merged_length * sizeof(char));
snprintf(snprintfResult, merged_length, "%s%s%s", first, second, third);
// catResult[merged_length] = '[=12=]'; // not necessary as per documentation
printf("snprintfResult:%s \tstrlen(snprintfResult):%d \tsizeof(snprintfResult):%d\n",
snprintfResult,
strlen(snprintfResult),
sizeof(snprintfResult));
free(snprintfResult);
}
Test Program Started
catResult:abc strlen(catResult):3 sizeof(catResult):4
snprintfResult:abc strlen(snprintfResult):3 sizeof(snprintfResult):4
snprintf
和 sprintf
不像 strcat
那样附加到先前的字符串。他们在传递给他们的缓冲区的开头开始写入。
在一次调用中写入多个字符串时,与格式字符串"%s%s%s"
一样,它们将连续写入字符串,它们之间没有空字符,并以空字符结尾。
如果您希望它们附加到名为 buffer
的缓冲区中的现有字符串,则确定字符串的长度,例如 n
,并将 buffer + n
作为第一个传递参数而不是 buffer
。 (对于 snprintf
,请注意还应从第二个参数中减去 n
,该参数指定缓冲区中可用的字节数。)
你不能那样使用 sizeof
。虽然 sizeof("string")
如您所愿,但 sizeof(string pointer)
在任何给定平台上总是 returns 相同的值(通常为 4 或 8)。
const int merged_length = (sizeof(first) + sizeof(second) + sizeof(third) + 1);
应该是
const int merged_length = (strlen(first) + strlen(second) + strlen(third) + 1);
当您将 %s
写入 snprintf
时,它会将字符串复制到目标字符串,不带任何尾随空值。当到达格式字符串末尾的 null 终止符时,输出字符串也以 null 终止。
所以,你的问题的实际答案是否定的,因为null在first
之后从来没有写过,但最终的效果更像是我们回答是的,因为这两个代码片段做同样的事情.