(GCC) Dollar sign in printf format string - c

I've seen the following line in a source code written in C:
printf("%2$d %1$d", a, b);
What does it mean?

It's an extension to the language added by POSIX (C11-compliant behaviour should be as described in an answer by #chux). Notation %2$d means the same as %d (output signed integer), except it formats the parameter with given 1-based number (in your case it's a second parameter, b).
So, when you run the following code:
#include <stdio.h>
int main() {
int a = 3, b = 2;
printf("%2$d %1$d", a, b);
return 0;
}
you'll get 2 3 in standard output.
More info can be found on printf man pages.

Per the C spec C11dr 7.21.6.1
As part of a print format, the first % in "%2$d %1$d" introduces a directive. This directive may have various flags, width, precision, length modifier and finally a conversion specifier. In this case 2 is a width. The next character $ is neither a precision, length modifier nor conversion specifier. Thus since the conversion specification is invalid,
... the behavior is undefined. C11dr 7.21.6.1 9
The C spec discusses future library directions. Lower case letters may be added in the future and other characters may be used in extensions. Of course $ is not a lower case letter, so that is good for the future. It certainly fits the "other character" role as $ is not even part of the C character set.
In various *nix implementations, $ is used as describe in Linux Programmer's Manual PRINTF(3). The $, along with the preceding integer defines the argument index of the width.

Related

Format string vulnerability in C (how does stack behave in this case?) [duplicate]

I've seen the following line in a source code written in C:
printf("%2$d %1$d", a, b);
What does it mean?
It's an extension to the language added by POSIX (C11-compliant behaviour should be as described in an answer by #chux). Notation %2$d means the same as %d (output signed integer), except it formats the parameter with given 1-based number (in your case it's a second parameter, b).
So, when you run the following code:
#include <stdio.h>
int main() {
int a = 3, b = 2;
printf("%2$d %1$d", a, b);
return 0;
}
you'll get 2 3 in standard output.
More info can be found on printf man pages.
Per the C spec C11dr 7.21.6.1
As part of a print format, the first % in "%2$d %1$d" introduces a directive. This directive may have various flags, width, precision, length modifier and finally a conversion specifier. In this case 2 is a width. The next character $ is neither a precision, length modifier nor conversion specifier. Thus since the conversion specification is invalid,
... the behavior is undefined. C11dr 7.21.6.1 9
The C spec discusses future library directions. Lower case letters may be added in the future and other characters may be used in extensions. Of course $ is not a lower case letter, so that is good for the future. It certainly fits the "other character" role as $ is not even part of the C character set.
In various *nix implementations, $ is used as describe in Linux Programmer's Manual PRINTF(3). The $, along with the preceding integer defines the argument index of the width.

What does a # sign after a % sign in a scanf() function mean?

What does the following code mean,in C
scanf("%d%#d%d",&a,&b,&c);
if given values 1 2 3 it gives output as 1 0 0
P.S- I know it is used with printf() statement but here in scanf() statement it gives random behaviour.
TL;DR; - A # after a % sign in the format string of scanf() function is wrong code.
Explanation:
The # here is a flag character, which is allowed in fprintf() and family, not in fscanf() and family.
In case of your code, the presence of # after % is treated as invalid conversion specifier. As per 7.21.6.2,
If a conversion specification is invalid, the behavior is undefined
So, your code produces undefined behaviour.
Hint: you can check the return value of scanf() to check how many elements were "scanned" successfully.
However, FWIW, using # with %d in printf() also is undefined behaviour.
Just for reference: As per the C11 standard document , chapter §7.21.6.1, flag characters part, (emphasis mine)
#
The result is converted to an ‘‘alternative form’’. For o conversion, it increases the precision, if and only if necessary, to force the first digit of the result to be a zero (if the value and precision are both 0, a single 0 is printed). For x (or X) conversion, a nonzero result has 0x (or 0X) prefixed to it. For a, A, e, E, f, F, g, and G conversions, the result of converting a floating-point number always contains a decimal-point character, even if no digits follow it. (Normally, a decimal-point character appears in the result of these conversions only if a digit follows it.) For g and G conversions, trailing zeros are not removed from the
result. For other conversions, the behavior is undefined.
According to the Standard, the use of # is illegal.
Its use makes your program invoke Undefined Behaviour.
Of course, if your implementation defines it, it is defined behaviour for your implementation and it does what your documentation says.

Large field widths in printf() in C

Do the C standards give any excuse for the program below not to produce gigabytes of spaces on its standard output?
#include <stdio.h>
int main()
{
// 2^64 = 18446744073709551616
printf("x%18446744073709551619dx\n", 42);
return 0;
}
Tested on Mac OS X 10.8 and on Linux, I get x 42x.
The C11 standard says (7.21.6.1:4): “An optional minimum field width. If the converted value has fewer characters than the field width, it is padded with spaces (by default) on the left (or right, if the left adjustment flag, described later, has been given) to the field width. The field width takes the form of an asterisk * (described later) or a nonnegative decimal integer.”
The wording in C99 is the same.
When the field width is given as *, then the corresponding argument is obtained as an int (7.12.6.1:5). But it does not seem to be said that the hardcoded field width should fit in an int.
Although it doesn't address the specific question of the field width encoding limit, note that §7.21.6.1/15 states "The number of characters that can be produced by any single conversion shall be at least 4095." So even if an implementation does parse 2^64 + 3 correctly, it's conforming to output 4094 spaces instead of "gigabytes".
Although the C standard does not define a maximum value I guess that every compiler has a maximum value for it.
Here is a similar question:
size limit of printf conversion specification

Why does scanf("%i",a) not take binary like 0b101?

I'm confused about the binary expression like 0b10101:
#include <stdio.h>
int main(void) {
int a,b;
b = 0b101;
scanf("%i",&a);
printf("the value of a is %d\n", a);
printf("the value of b is %d\n", b);
}
when I type 0b101,
the output gives me
the value of a is 0;
the value of b is 5;
instead of two 5's as it should be.
Is there any way to make scanf take binary input?
Standard C has no specific notation prefix for representing binary notation. Only decimal, octal and hexadecimal are supported. Although the 0b prefix was proposed for C99 (and rejected), so it is probably not unusual to see it implemented in some compilers.
Even if you saw 0b prefix supported by some specific C implementation as an extension (GCC?), it would be rather surprising see it recognized by scanf's %i format specifier, since it would break compatibility with standard implementations. The latter are required to stop reading at b.
Judging by your test results though it appears that the compiler supports 0b... integral literals, while the standard library knows nothing about them. Maybe the documentation for that library has something to say about it, like some extended non-standard format specifier/flag for scanf that makes it recognize 0b... prefixes. I don't see it in GCC docs though.

Scanf syntax - %6d and %-6d and %0d

What are the differences between using scanf with the following format specifiers, when the input being scanned is 123456 versus when it's 123:
%6d
%-6d
%0d
What are the differences in the output?
I ended up just trying it with GCC 4.3.4, and got the following:
%6d: Works fine; only reads 6 characters (so if you try to read 123456789 it will only read 123456)
%-6d: Emits the warning:
warning: unknown conversion type character '-' in format
Doesn't read anything, and the int being written to is unmodified
%0d: Emits the warning:
warning: zero width in scanf format
Reads as though there were no width in the format specifier (%d)
I haven't checked the spec to see if those results are mandated or just how GCC handles it (EDIT: AndreyT found it)
The %-6d is an invalid format specifier. There are no format specifiers with - in them in scanf.
In %6d the 6 part is called maximum field width. It works with all format specifiers (not only with d) and specifies the maximum number of characters to read before any format-specific conversion is performed. For example, if input sequence is 1234567, then %3d will read and convert 123 and %6d will read and convert 123456.
The %0d is an invalid format specifier. Maximum field width in scanf must be a non-zero integer (see 7.19.6.2/3 in the language specification).
So, that leaves us with %6d as the only meaningful format specifier among the three you provided. Under these circumstances the question about differences in output (in results?) makes little sense.
EDIT: One can probably argue that in %-6d the -6 part is the maximum field width, which satisfies the standard requirement of being non-zero decimal integer. However, in C language terminology a decimal integer as a lexical element is a sequence of digits and digits only. It is not allowed to include a sign. I.e. neither -6 nor +6 are decimal integers. Every time you use -6 or +6 as integers in your program it is actually unary - and + operator lexeme followed by decimal integer lexeme. So, since the specification of scanf requires a non-zero decimal integer as maximum field width, it must be a sign-less integer.
Here's what I think will happen: %6d will get you the first 6 digits of the number, %-6d will probably not work as you expect, since - is more of an output alignment specifier. %0d would mean you want only 0 characters, which would probably not work as expected.
Both %-6d and %0d are invalid conversion specifications for scanf, so the behavior for those cases will be undefined. See the language standard, § 7.19.6.2, ¶ 3.
I'll assume, like Arkadiy, that you really meant printf-style formatting, since you refer to "output". I'll also assume that you're using C (as the tag suggests).
If you run:
printf("%6d %-6d %0d", num1, num2);
...you'll end up with compiler errors (or, worse still, runtime bugs), as you haven't supplied enough arguments for three formats.
I've a feeling that that's not what you were asking, though. Let's assume that you actually run:
// (I've added some extra stuff to show how the formatting works.)
printf("'%6d'/'%-6d'/'%0d'", num2, num2, num2);
...you'll get:
' 123'/'123 '/'123'
Normally, if the field width (6 in this case) is wide enough, numbers are right-aligned, space-padded. If you put a '-' before the field width, they will be right-aligned, space-padded.
The subtlety here is in the "%0d" format. You might think you're specifying a zero-width field...and you'd be wrong. The first thing after the '%' is an option flag, and '0' is a valid flag. It means, "If the field width is wider than the content, left-pad with zeroes." In this case, you haven't supplied a field width (the '0' is a flag, remember?), so the '0' flag has no effect: the field will be as wide as the content requires.
There's an even worse subtlety, though. If you specified "%-06d", you'd get right-padding with zeroes, right? Um, no. The '-' flag overrides the '0' flag, whichever order they're supplied. You'd get '123 '.

Resources