Undefined behavior of printf in C? - c

What should be the output of a single percent sign?
#include <stdio.h>
void main()
{
printf("%");
}
"Unknown format code" is not like "Unknown escape sequence".

What you're doing is undefined behavior.
Section 7.21.6.1p9 of the C standard regarding format specifiers for fprintf (and by extension printf) states:
If a conversion specification is invalid, the behavior is undefined. If any argument is
not the correct type for the corresponding conversion specification, the behavior is
undefined.
Also, gcc will generate a warning with -Wall if you do this:
warning: spurious trailing ‘%’ in format [-Wformat=]
The correct way to print a % character is with the format specifier %%.
printf("%%");

% is used to signal that you want to print a variable e.g.
int i = 10;
printf("%d", i); //prints 10
In order to just print the '%' sign you must escape it as
printf("%%");

Related

What is the 'I' (capital i) flag in C printf?

While compiling the following code:
#include <stdio.h>
int main() {
printf("99% Invisible");
return 0;
}
in gcc 7.5.0 I get the following warnings:
test.c: In function ‘main’:
test.c:4:16: warning: ' ' flag used with ‘%n’ gnu_printf format [-Wformat=]
printf("99% Invisible");
^
test.c:4:16: warning: 'I' flag used with ‘%n’ gnu_printf format [-Wformat=]
test.c:4:16: warning: format ‘%n’ expects a matching ‘int *’ argument [-Wformat=]
printf("99% Invisible");
~~~^
What is going on here? I don't see mention of a " " flag or an "I" flag anywhere in documentation. The code outputs 99visible, essentially ignoring the space and I in the format string and following the %n format.
edit: People seem to be misunderstanding the question. I know how to printf a literal %, and what %n do. I am just curious what is happening here.
(also, for those who know the context: I know the system in question didn't use C, I am just curious as to what printf is doing here).
The I flag is a GNU extension to printf. From the man page:
glibc 2.2 adds one further flag character.
I
For decimal integer conversion (i, d, u) the output uses the
locale's alternative output digits, if any. For example, since glibc
2.2.3 this will give Arabic-Indic digits in the Persian ("fa_IR") locale.
So when the compiler checks the format string, it sees % In as a format specifier, i.e. the space and I flags applied to the n conversion specifier. Since neither flag is applicable to the n conversion specifier, the compiler emits a warning for each.
To print the literal %, you must write %%.
https://en.cppreference.com/w/c/io/fprintf
I flag is not in the C standard.
It appears that with your compiler when a % character is encountered in a printf format string, it scans forward to find a valid format specifier, then interprets everything in-between as a modifier. If those are not valid modifiers, an error is flagged.
As others have pointed out, replace "99% Invisible" with "99%% Invisible" to fix the problem.

Am I using conversion specifiers wrong or something? scanf() isn't working in c

scanf() isnt working properly when I use the following lines of code in c:
double withdraw = 0;
scanf("%.2lf",&withdraw);
printf("\n\nWithdraw %.2lf?",&withdraw);
and this:
double withdraw = 0;
scanf("%.2lf",withdraw);
printf("\n\nWithdraw %.2lf?",withdraw);
and this:
double withdraw = 0;
scanf("%.2lf",&withdraw);
printf("\n\nWithdraw %.2lf?",withdraw);
and finally this:
double withdraw = 0;
scanf("%.2lf",withdraw);
printf("\n\nWithdraw %.2lf?",&withdraw);
input into scanf() is ALWAYS this:
1
output of withdraw is ALWAYS this:
0.00
Please help. This seems so crazy to me!
Yes, your code is wrong. You cannot use precisions (".<int>") with fscanf() family, that's invalid. This causes causes undefined behavior.
Quoting C11, chapter §7.21.6.2/p3, fscanf()
Each conversion specification is introduced by the character %.
After the %, the following appear in sequence:
— An optional assignment-suppressing character *.
— An optional decimal integer greater than zero that specifies the maximum field width
(in characters).
— An optional length modifier that specifies the size of the receiving object.
— A conversion specifier character that specifies the type of conversion to be applied.
and, p13
If a conversion specification is invalid, the behavior is undefined.
That said, do not use trial and error, undefined behaviors are tricky to catch and understand. read the manual pages for proper format specifier for any argument type.
As your compiler is telling you
warning: unknown conversion type character ‘.’ in format [-Wformat=]
So you cannot specify precision with this type of format specifier
The following could work.
#include <stdio.h>
#include <math.h>
int main()
{
double withdraw = 0;
scanf("%lf", &withdraw);
printf("\n\nWithdraw %.2lf?", withdraw);
return 0;
}

Macro variable substitution in printf

I wrote a simple program with a single printf statement,like hello world.
#include <stdio.h>
#define MAX 100
int main()
{
printf("Max is %d\n",MAX);
}
I studied that macros are just substituted in place of occurrence ,by preprocessor. Generally printf need a variable name with corresponding format specifier to print the value of variable.
Here ,with my understanding, 100 should be replaced in printf call and should raise an error.
But the output is :
Max is 100
How and why?
"Generally printf() need a variable name with corresponding format specifier to print the value of variable."
There you went wrong. All the format specifiers supplied with printf() expects an argument of the particular type, not a variable of that type. 100, an integer literal, is a valid argument for %d, in this case.
So, printf("Max is %d\n",100); is both a valid and legal statement in C. The output you got is expected output, there should be no error or warning with this.
Just to add a reference to the actual words, quoting C11, chapter §7.21.6.1, fprintf() (emphasis mine)
d,i
The int argument is converted to [...]
The printf format "%d" tells printf to extract an int argument from the argument list. If that int comes from a variable or a literal doesn't matter.

Why does printf("%%") print only one percent (%) symbol? [duplicate]

This question already has answers here:
How to escape the % (percent) sign in C's printf
(13 answers)
Closed 8 years ago.
When I run this following code:
#include <stdio.h>
#include <conio.h>
void main(){
clrscr();
printf("%%");
getch();
}
I get % as an output?
What might be the reason behind this logic?
That is what printf does: it is print formatted (f for formatted). It uses % as the formatting character. It is the only reserved character and needs to be escaped to represent it self, i.e. %%. See the manual for more information on formatting: printf.
P.S.: Never use a string that is not a part of the program as the first argument. To print a string message that was input by a user, do printf(%s, message);. Otherwise you will have a security hole in your code.
% comes into format specifiers.
Example
When we write printf("%d", 20);, it will print 20 rather than %d. because the compiler treats % as a format specifier. In the mind of the compiler, the meaning of % is somewhat special.
So if you want that "%" should be the output, then you must write printf("%%"). Here the first % sign will suppress the meaning of the % format specifier and will print % as an output.
From the standard ISO/IEC 9899:1999 (E)
7.19.6.1
Each conversion specification is introduced by the character %.
The conversion specifiers and their meanings are:
% - A % character is written. No argument is converted. The complete
conversion specification shall be %%.
For C printf, % is a special character which typically indicates a parameter to substitute at that position: printf("Hello, %s\n", "World!"); results in "Hello, World!". There are lots of different things you can put after the % depending on the data you want to output. So that leaves the problem of "What if I want to print a percent symbol"?
The solution: Use %%.
The same is true of the special escape character \. "\n" means to print a new line. If you want to actually print the forward slash, you have to put it twice \\
See Printf format string and MSDN.

printf format string lint warning

I'm stuck fixing ancient code, and here is today's issue:
output_file_status = fprintf ( data_file, "%03d%08s%+014.2f%06.3f%",
LongValue, CharStarValue, Double1, Double2 );
Lint32 produces: Lint32 results in “malformed format string”
1) Do you all agree the format string can not end in a % sign? I don't believe a standalone % has meaning.
2) When I either remove the trailing %, or append an additional %, I still get the same warning.
This is using the Oracle Pro*C compiler (so the CharStarValue is actually a (char*)VarChar.arr ).
Yes, you are correct that % by itself at the end is an error. It should be %% to produce one literal % in the formatted output.
It might be that your linter is also complaining about the use of %03d with a long value. That should be %03ld.
Taking it piece by piece:
"%03d" expects an int. OP supplies a LongValue. With a long, specifier should be "%03ld".
"%08s" expects a pointer to char. OP supplies CharStarValue. OK. But the "0" in the specifier is undefined behavior for a %s. Recommend "%8s"
"%+014.2f" expects a double. OK. Flags '+', '0' are OK.
"%06.3f" expects a double. OK. Flags '+', '0' are OK.
"%" should have something after it else behavior is undefined. Recommend removal or "%%".
To OP's 2 points
1 A proper format should not end with a lone %, but may end with paired %%s.
A standalone % introduces "If a conversion specification is invalid, the behavior is undefined" C11 7.21.6.1 9.
2 To get rid of all warnings, try "%03ld%8s%+014.2f%06.3f".

Resources