在这种情况下,您可能应该编写以下内容之一:
char str1[10] = "%any";
char str1[] = "%any"; // str1 has size 5
const char *str1 = "%any"; // str1 points to a string literal
%a
在格式化字符串中是十六进制浮点格式。除了您没有提供double
参数(导致未定义的行为)这一事实之外,这可能会写入超过 10 个字节并因此超出您的缓冲区str1
(导致未定义的行为)。
这就是为什么您会看到0x0.07fff00000001p-1022ny
,它是一个十六进制浮点值0x0.07fff00000001p-1022
,后跟ny
. 您得到的非法指令错误可能是因为您破坏了存储在堆栈中的返回地址,因此当您的函数返回时,它会跳转到无效地址。
根据经验,如果您使用其中一个printf
函数并且没有在格式字符串后指定至少一个可变参数,那么您很有可能做错了什么。f
in的含义printf
是该函数进行格式化,但是当您没有任何要格式化的内容时,您正在使用它。所以它只是一个字符串副本,有额外的机会出错。
如果您想使用printf
函数系列中的一个来编写字符串,那么您可以避免意外指定您不希望这样的格式:
sprintf(str1, "%s", SOME_STRING);
或利用长度检查:
#define STR1_SIZE 10
char str1[STR1_SIZE];
if (snprintf(str1, STR1_SIZE, "%s", SOME_STRING) >= STR1_SIZE) {
// error-handling here
}
如果您以某种方式知道它SOME_STRING
适合您的缓冲区,那么您可以省略错误处理和/或strcpy
改用。但是当你这样做并且弄错长度时,你看起来很愚蠢。
您还可以使用数组(因为它在这里)而不是指针(因为它在大多数字符串处理代码中)sizeof(str1)
来代替STR1_SIZE
提供的。str1
我尝试转义,即在 sprintf 中使用“\%any”而不是“%any”;但这无济于事。
不错的尝试,没有雪茄 ;-)
反斜杠用于转义字符串文字中的特殊字符。由于%
在字符串文字中没有任何特殊含义,因此转义它没有任何效果。结果字符串是五个字符%
, a
, n
, y
, \0
。
稍后您将该字符串传递给sprintf
. 现在具有%
特殊含义,并且有不同的转义方式:%%
.