In this case you should probably write one of the following:
char str1[10] = "%any";
char str1[] = "%any"; // str1 has size 5
const char *str1 = "%any"; // str1 points to a string literal
%a
in a formatting string is a hex floating point format. Aside from the fact you didn't supply a double
argument (causing undefined behavior), this can write more than 10 bytes and hence overrun your buffer str1
(causing undefined behavior).
That's why you see 0x0.07fff00000001p-1022ny
, it's a hex floating-point value 0x0.07fff00000001p-1022
followed by ny
. Probably the illegal instruction error you get is because you smashed the return address stored on the stack, so when your function returns it jumps to an invalid address.
As a rule of thumb, if you use one of the printf
functions and you don't specify at least one vararg after the format string, there's a reasonable chance that you're doing something wrong. The meaning of the f
in printf
is that the function does formatting, but you're using it when you don't have anything to format. So it's just a string copy with an extra opportunity to get it wrong.
If you want to use one of the printf
family of functions to write a string, then you can avoid accidentally specifying a format you didn't mean like this:
sprintf(str1, "%s", SOME_STRING);
or to take advantage of length-checking:
#define STR1_SIZE 10
char str1[STR1_SIZE];
if (snprintf(str1, STR1_SIZE, "%s", SOME_STRING) >= STR1_SIZE) {
// error-handling here
}
If you somehow know that SOME_STRING
fits in your buffer, then you could omit the error-handling and/or use strcpy
instead. But you look pretty stupid when you do that and get the lengths wrong.
You can also use sizeof(str1)
in place of STR1_SIZE
provided that str1
is an array (as it is here) rather than a pointer (as it is in most string-handling code).
I tried escaping, i.e using "\%any" instead of "%any" in sprintf; but this doesn't help.
Nice try, no cigar ;-)
The backslash is to escape special characters in a string literal. Since %
doesn't mean anything special in a string literal, escaping it has no effect. The resulting string is five characters %
, a
, n
, y
, \0
.
Later you pass that string to sprintf
. Now the %
has special meaning, and has a different way of escaping it: %%
.