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

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.

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.

Result of Printf ("%d", &a)

I have a code in C .
int a;
a =10;
printf ("%d", &a);
I want to know if some garbage will be printed or error msg will be shown.
Basically I am interested in knowing how printf works. Does it have a list of variables in a table sort of things. If a table is there from where it will take the value of &a
This is a beginners question and deserves to be answered properly. (I'm startled by the downvotes and the non-constructive comments)
Let me give a walk-throu line by line:
int a;
The first line declares a variable with the name a. The variable is of type integer and with normal compilers (Microsoft Visual C++ on Windows, GCC on linux, Clang on Mac) this usually 32 bits wide. The integer variable is signed because you did not specify unsigned. This means it can represent values ranging from –2,147,483,648 to 2,147,483,647.
a =10;
The second line assigns the value 10 to that variable
printf ("%d", &a);
The third line is where you get the surprising result. "%d" is the "format string" it defines how the variables, given as further arguments are formatted and subsequently printed. The format string comprises of normal text (which will be printed normally) and control-sequences. the control sequences start with the character % and end with a letter. The letter specifies the argument type that is expected. d in the above case expects a integer value.
The problem with your code is that you do not specify an itenger value, you give the address of an integer value (with the address-of & operator). The correct statement would be:
printf ("%d", a);
Simple.
I recommend that you have a read on a good C book. I recommend "The C programming language" which is from the original authors of the language. You find this book on amazon, but you find it also online.
You can find the same answers reading in the standard. But to be honest, these documents are not easy reading. You can find a draft of the C11 standard here. The description of the formatting options starts on page 309. (drafts are usually good enough for programming purposes, and are usually available for free).
This is undefined behaviour.
If you are new to C, this may be a surprise. However the C specification defines the behaviour of certain programs (called "correct programs"). If you do not follow the rules in the specification, then your program is not correct, and literally anything may happen. The above link goes into more detail.
Your program doesn't follow the rules because the %d format specifier for printf must have a corresponding argument of type int (after the default argument promotions), but instead you pass an argument of type int *.
Since it is undefined behaviour, the output is meaningless and it is generally not worthwhile to investigate.
It will print the address of the variable 'a'. Remember that the & operator returns the address of the operand.

Why does %d show two different values for *b and *c in the code [b and c points to same address]

Consider the Code below
{
float a=7.999,*b,*c;
b=&a;c=b;
printf("%d-b\n%d-c\n%d-a\n",*b,*c,a);
}
OUTPUT:
-536870912-b
1075838713-c
-536870912-a
I know we are not allowed to use %d instead of %f, but why does *b and *c give two different values?
Both have the same address, can someone explain?
I want to know the logic behind it
Here is a simplified example of your ordeal:
#include <stdio.h>
int main() {
float a=7.999, b=7.999;
printf("%d-a\n%d-b\n",a,b);
}
What's happening is that a and b are converted to doubles (8 bytes each) for the call to printf (since it is variadic). Inside the printf function, the given data, 16 bytes, is printed as two 4-byte ints. So you're printing the first and second half of one of the given double's data as ints.
Try changing the printf call to this and you'll see both halves of both doubles as ints:
printf("%d-a1\n%d-a2\n%d-b1\n%d-b2\n",a,b);
I should add that as far as the standard is concerned, this is simply "undefined behavior", so the above interpretation (tested on gcc) would apply only to certain implementations.
There can be any number of reasons.
The most obvious -- your platform passes some integers in integer registers and some floating point numbers in floating point registers, causing printf to look in registers that have never been set to any particular value.
Another possibility -- the variables are different sizes. So printf is looking in data that wasn't set or was set as part of some other operation.
Because printf takes its parameters through ..., type agreement is essential to ensure the implementation of the function is even looking in the right places for its parameters.
You would have to have deep knowledge of your platform and/or dig into the generated assembly code to know for sure.
Using wrong conversion specification invokes undefined behavior. You may get either expected or unexpected value. Your program may crash, may give different result on different compiler or any unexpected behavior.
C11: 7.21.6 Formatted input/output functions:
If a conversion specification is invalid, the behavior is undefined.282) If any argument is
not the correct type for the corresponding conversion specification, the behavior is
undefined.
// Bad
float a=7.999,*b,*c;
b=&a;c=b;
printf("%d-b\n%d-c\n%d-a\n",*b,*c,a);
// Good
float a=7.999,*b,*c;
b=&a;c=b;
printf("%f-b\n%f-c\n%f-a\n",*b,*c,a);
Using an integer format specified "%d" instead of correctly using a float specified "%f" is what alk elliptically fails to explain as "undefined behavior".
You need to use the correct format specifier.

How to declare bits in C?

I'm trying to do this :
uint64_t key = 0110000010110110011001101111101000111111111010001011000110001110;
Doesn't work. GCC says
warning: integer constant is too large for its type
Any idea why?
Although neither the draft C99 standard nor the draft C11 standard support binary literals, since you specifically mention gcc it has an extension for binary literals which says:
Integer constants can be written as binary constants, consisting of a sequence of ‘0’ and ‘1’ digits, prefixed by ‘0b’ or ‘0B’. This is particularly useful in environments that operate a lot on the bit level (like microcontrollers).
they gives the following example (see it live):
i = 0b101010;
and it looks like clang also support this as an extension as well (see it live):
[...]binary literals (for instance, 0b10010) are recognized. Clang supports this feature as an extension in all language modes.
This is not available in standard C++ either until C++14 [lex.icon].
Due to the leading 0 that's read as a very large octal literal, which is probably not what you want. Amazingly, C doesn't have binary literals.
As an extension, gcc supports binary literals with the 0b prefix, eg, 0b101010. If you don't want to rely on extensions, hexadecimal is probably the most reasonable alternative.
Use Hex decimal they are more compact and can represent binary example:
0x01 // This is 0001
0x02 // 0010
Using binary the way you want is particularly ugly inside someone's code.
Also starting a number with 0 (in your example) will be interpreted as octal.
To add to #Shafik's answer:
#include <inttypes.h>
#include <stdio.h>
int main(void)
{
uint64_t i = UINT64_C(
0b0110000010110110011001101111101000111111111010001011000110001110);
printf("%" PRIX64 "\n", i) ;
return 0;
}
Worked with: gcc -std=gnu99 - output: 60B666FA3FE8B18E
Really, embedded systems are much more strict about extensions, particularly if you're unfortunate enough to be required to adhere to standards like MISRA-C. Hexadecimal conversion is just the grouping of 4 binary digits to 0x0 -> 0xf.
I think that is because you exceeded the maximum integer that can be stored in an uint datatype.
Try using an array of boolean type.

(GCC) Dollar sign in printf format string

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.

Resources