#include <stdio.h>
int main(void)
{
char i=49;
printf("%d",i);
return 0;
}
Why does the output is 49?
I am using %d to print a character, whereas my character declaration is also wrong.
In C a char means the same thing as a byte; it is the smallest addressable piece of memory, and also a smallest of integer types. 49 is an integer constant of type int having the value 49. '1' is a character constant, that also has type int! And on ASCII systems'1' as the value 49 (the ASCII code of character 1).
printf conversion specifier %d expects the corresponding argument to be an int, whose value is then printed in decimal notation. The remaining arguments after the format string are subject to default argument promotions; each integer type smaller than int is promoted to an int; and float is promoted to double. Since i has an integer type smaller than int, its value (49) is now promoted to an int and to printf it looks exactly the same as if any other integer value 49 was given.
To print the character whose character code is 49, you need to use the %c conversion specifier; printf will then output 1, which is the character by code 49; even now, the argument is promoted to int, and printf internally converts that value to an unsigned char, which then will be output (source):
c
[...] the int argument is converted to an unsigned char, and the resulting character is written. [...]
Addendum: in code
char i = 49.012;
printf("%f", i);
49.012 is a value of type double; this is converted to char-range integer by chopping the decimals, thus the value stored in i is yet again 49; which one can prove by printing it with %d. Now, %f expects that the corresponding argument is of type double but i is converted to an int instead; using an argument of wrong type in call to printf has undefined behaviour, i.e. anything can happen. If one compiles with gcc -Wall, the following error is produced:
warning: format %f expects argument of type double, but argument 2 has type int [-Wformat=]
Updating answer based on comments.
char is an integer type, and you assign 49 to this integer type. The %d conversion specifier prints the value of an integer;
char i=49;
If you print using "%c" you can see the corresponding character of ascii value 49 ie 1
Since you are using "%d" you get the integer value itself.
You can try this
char i='1';
Now try printf("%d",i);
You will get 49
%d,%c,%o,%x... these are called format specifier. it will decide which type of output you want.
in your example, you assigned 49 to i and saying to compiler that you want the output in decimal.
if you try to print the same by substituting %d with %c, then it will print
1 because it assumes the output should be print in the form of char equivalent of the given number
where in ASCII table 49 is 1
and FYI
in the implementation of printf function they will deal '%' symbol followed by the character as special case
if the followed character is valid then it will output
%x is hex
%d is decimal
%i is integer
%c is character
%s is string
%f is float
............... etc
you can google "formal specifier in c" there will be plenty of results
hope this info useful to you.
Related
#include<stdio.h>
int main()
{
int i = 577;
printf("%c",i);
return 0;
}
After compiling, its giving output "A". Can anyone explain how i'm getting this?
%c will only accept values up to 255 included, then it will start from 0 again !
577 % 256 = 65; // (char code for 'A')
This has to do with how the value is converted.
The %c format specifier expects an int argument and then converts it to type unsigned char. The character for the resulting unsigned char is then written.
Section 7.21.6.1p8 of the C standard regarding format specifiers for printf states the following regarding c:
If no l length modifier is present, the int argument is converted to an
unsigned char, and the resulting character is written.
When converting a value to a smaller unsigned type, what effectively happens is that the higher order bytes are truncated and the lower order bytes have the resulting value.
Section 6.3.1.3p2 regarding integer conversions states:
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or
subtracting one more than the maximum value that can be represented in the new type
until the value is in the range of the new type.
Which, when two's complement representation is used, is the same as truncating the high-order bytes.
For the int value 577, whose value in hexadecimal is 0x241, the low order byte is 0x41 or decimal 65. In ASCII this code is the character A which is what is printed.
How does printing 577 with %c output "A"?
With printf(). "%c" matches an int argument*1. The int value is converted to an unsigned char value of 65 and the corresponding character*2, 'A' is then printed.
This makes no difference if a char is signed or unsigned or encoded with 2's complement or not. There is no undefined behavior (UB). It makes no difference how the argument is passed, on the stack, register, or .... The endian of int is irrelevant. The argument value is converted to an unsigned char and the corresponding character is printed.
*1All int values are allowed [INT_MIN...INT_MAX].
When a char value is passed as ... argument, it is first converted to an int and then passed.
char ch = 'A';
printf("%c", ch); // ch is converted to an `int` and passed to printf().
*2 65 is an ASCII A, the ubiquitous encoding of characters. Rarely other encodings are used.
Just output the value of the variable i in the hexadecimal representation
#include <stdio.h>
int main( void )
{
int i = 577;
printf( "i = %#x\n", i );
}
The program output will be
i = 0x241
So the least significant byte contains the hexadecimal value 0x41 that represents the ASCII code of the letter 'A'.
577 in hex is 0x241. The ASCII representation of 'A' is 0x41. You're passing an int to printf but then telling printf to treat it as a char (because of %c). A char is one-byte wide and so printf looks at the first argument you gave it and reads the least significant byte which is 0x41.
To print an integer, you need to use %d or %i.
int a=65;
printf("%c", a);
I tried it on GCC on Ubuntu I don't know the version. But it worked and I wish to know how?
Because according to me the size of char is smaller than int and hence it shouldn't have been possible.
The printf function has the following declaration:
int printf(const char *format, ...);
The first argument must be a pointer to a char array, but any additional arguments can be of any type, so it's not a compiler error if a format specifier mismatches the parameter (although it is undefined behavior).
This still works however because of what %c expects. From the man page:
If no l modifier is present, the int argument is converted to an
unsigned char, and the resulting character is written. If an l
modifier is present, the wint_t (wide character) argument is
converted to a multibyte sequence by a call to the wcrtomb(3)
function, with a conversion state starting in the initial state,
and the resulting multibyte string is written.
From the above passage, %c actually expects an int and converts it to an unsigned char for printing. So if that's the case why does passing an actual char work? That is because of integer promotions. Any integer type smaller than int is promoted to int anyplace an int can be used. Since printf is variadic it can't check the types of its arguments, so a char passed to printf will get promoted to int when the function is called.
7.21.6.1 The fprintf function
...
8 The conversion specifiers and their meanings are:
...
c If no l length modifier is present, the int argument is converted to an
unsigned char, and the resulting character is written.
If an l length modifier is present, the wint_t argument is converted as if by
an ls conversion specification with no precision and an argument that points
to the initial element of a two-element array of wchar_t, the first element
containing the wint_t argument to the lc conversion specification and the
second a null wide character.
C 2011 Online Draft
So, (f)printf expects the argument corresponding to the %c conversion specifier to have type int, and will convert it to unsigned char before formatting and displaying.
The value 65 can certainly fit in an unsigned char (0-255), so there's no problem with the conversion there. If you pass an integer value outside that range, then I suspect the following comes into play:
6.3 Conversions
6.3.1.3 Signed and unsigned integers
...
2 Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or
subtracting one more than the maximum value that can be represented in the new type
until the value is in the range of the new type.60)
60) The rules describe arithmetic on the mathematical value, not the value of a given type of expression.
IOW, if you pass the value 321, it should "wrap" around back to 65 ('A' in ASCII).
This is because of the default argument promotions. Anything smaller than int, when passed as part of printf's variable argument list, is converted to int before the call. Therefore, printf("%c", foo) cannot tell the difference between char foo and int foo. (However, if the value of the datum passed to %c is outside the range of unsigned char, the behavior is undefined.)
It worked because it just print the the value of 65 converted to a char type in ASCII table 65 is the letter A so when you put:
int a = 65;
printf("%c", a); //---> a coverted to char type.
Check the ASCII table here ASCII table
long int id;
printf("Enter Aircraft Id: (eg abeb11");
scanf("%x",&id);
The id" has to be read as hex value.
but I am getting the warning format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘long int’ [-Wformat=]
In C++, we can use setbase().
But I am stuck as to how to do it in C.
You can use %lx format specifier to read in the long hex value.
Also scanf wants the address of the variable to read in.
scanf("%x",id); this will lead to Undefined Behavior.
Hence change as below.
printf("Enter Aircraft Id: (eg abeb11");
scanf("%lx",&id);
No there is not, the standard input/output streams in C are much more low-level and do not support the concept of a base (nor the concept of outputting "a number", they are character streams).
Just use printf():
const int number = 4711;
printf("%d in hex is %x; in octal it's %o\n", number, (unsigned int) number,
(unsigned int) number);
will print:
4711 in hex is 1267, in octal it's 11147
And no, there's no standard way of printing in binary, you're going to have to implement that on your own if you need it.
To input, you need to match the type of the variable with the type implied by the formatting specifier:
if(scanf("%lx", &id) == 1)
{
printf("the ID is %lu (0x%lx)\n", id, id);
}
the type of hexadecimal numbers is unsigned with the printf() and scanf() family of functions.
C++ has a type safe conversion system for reading values from standard streams. setbase(16) is used to change the input base, not to specify the type of the target, which is handed automatically.
in C, the scanf() function uses a format string to specify both the type of the target variable and how to convert it, it has no information about the actual type of the remaining arguments. scanf() supports decimal, octal and hexadecimal conversions:
%d converts an optionally signed value expressed in decimal into an int variable
%u converts an optionally signed value expressed in decimal into an unsigned int variable
%o converts an optionally signed value expressed in octal into an unsigned int variable
%x converts a optionally signed value expressed in hexadecimal into an unsigned int variable,
%lx does the same for an unsigned long int variable. There is no way to tell scanf() that the target variable is a long int, passing the address of a long int for %lx has undefined behavior, but it is accepted and works correctly for positive values on most current systems.
%i converts a optionally signed value expressed in decimal, octal or hexadecimal into an int variable. The base is determined from the initial prefix (after optional spaces and an optional sign): 0 for octal, 0x for hexadecimal, otherwise decimal.
Note that you should test the return value of scanf() to detect invalid or missing input.
Here is a modified version:
unsigned long int id;
printf("Enter Aircraft Id (eg abeb11): ");
if (scanf("%lx", &id) != 1) {
printf("Invalid input\n");
...
}
Is the output of the following programm 1 or 0, or is it undefined behaviour?
int main() {
unsigned char u = 10;
sscanf("1025","%hhu",&u);
printf("u, is it 0 or is it 1? u's value is ... %hhu", u);
}
According to fscanf conversion specifier %u with length modifier hh (i.e. %hhu), semantics is defined based on that of strtoul function and a mapping to type pointer to unsigned char:
12) The conversion specifiers and their meanings are:
"u"
Matches an optionally signed decimal integer, whose format is the same
as expected for the subject sequence of the strtoul function with the
value 10 for the base argument. The corresponding argument shall be a
pointer to unsigned integer.
11) The length modifiers and their
meanings are:
"hh" Specifies that a following d, i, o, u, x,
X, or n conversion specifier applies to an argument with type pointer
to signed char or unsigned char.
But what happens if an input sequence represents an integral value exceeding 8 bits, which part of the integral value is mapped to the 8 bits of an unsigned char? Is it defined that it has to be the least significant part, does it depend on endianess, is it unspecified, or does it even yield undefined behaviour?
I cannot believe that it is undefined or unspecified behaviour. This would mean that user input might introduce such behaviour in a program using scanf("%hhu",&u), and checking user input before every use of scanf looks absurd to me.
Undefined. See one section up:
10 Except in the case of a % specifier, the input item (or, in the case of a %n directive, the count of input characters) is converted to a type appropriate to the conversion specifier. If the input item is not a matching sequence, the execution of the directive fails: this condition is a matching failure. Unless assignment suppression was indicated by a *, the result of the conversion is placed in the object pointed to by the first argument following the format argument that has not already received a conversion result. If this object does not have an appropriate type, or if the result of the conversion cannot be represented in the object, the behavior is undefined.
I am learning C from the book "C Primer Plus" by Stephen Prata. In chapter 4, the author states that in printf(), %o and %x, denote unsigned octal integers and unsigned hexadecimal integers respectively, but in scanf(), %o and %x, interpret signed octal integers and signed hexadecimal integers respectively. Why is it so?
I wrote the following program in VS 2015 to check the author's statement:
#include <stdio.h>
int main(void)
#pragma warning(disable : 4996)
{
int a, b, c;
printf("Enter number: ");
scanf("%x %x", &a, &b);
c = a + b;
printf("Answer = %x\n", c);
while (getchar() != EOF)
getchar();
return 0;
}
The code proved the author's claim.
If the inputs had a pair integers where the absolute value of the positive integer was bigger than the absolute value of the negative integer, then everything worked fine.
But if the inputs had a pair integers where the absolute value of the positive integer was smaller than the absolute value of the negative integer, then the output was what you would expect from unsigned 2's complement.
For example:
Enter number: -5 6
Answer = 1
and
Enter number: -6 5
Answer = ffffffff
The C standard says that for printf-like functions (7.21.6.1 fprintf):
o,u,x,X
The unsigned int argument is converted to unsigned octal
(o), unsigned decimal (u), or unsigned hexadecimal notation (x or X)
While for scanf-like functions it says (7.21.6.2 fscanf):
x
Matches an optionally signed hexadecimal integer, whose format is the same
as expected for the subject sequence of the strtoul function with the value
16 for the base argument. The corresponding argument shall be a pointer to
unsigned integer.
So as an extra feature, you can write a negative hex number and scanf will convert it to the corresponding unsigned number in the system's format (two's complement).
For example
unsigned int x;
scanf("%x", &x); // enter -1
printf("%x", x); // will print ffffffff
Why they felt like scanf needed this mildly useful feature, I have no idea. Perhaps it is there for consistency with other conversion specifiers.
However, the book seems to be using the function incorrectly, since the standard explicitly states that you must pass a pointer to unsigned int. If you pass a pointer to a signed int, you are formally invoking undefined behavior.
Reading the C11 specification, section 7.21.6.2/12, it says for the o format:
Matches an optionally signed octal integer, whose format is the same as
expected for the subject sequence of the strtoul function with the value 8
for the base argument. The corresponding argument shall be a pointer to
unsigned integer.
With corresponding text for the hexadecimal x format.
So on one hand the specification says the input can be signed, but it also says the format is the same as for the strtoul function which reads unsigned integers, and the result is stored in an unsigned integer.
Indeed the author is wrong as #Joachim Pileborg pointed out
This is what the standard says about it
7.21.6.2 The fscanf function1
12 The conversion specifiers and their meanings are:
o Matches an optionally signed octal integer, whose format is the same as
expected for the subject sequence of the strtoul function with the value 8
for the base argument. The corresponding argument shall be a pointer to
unsigned integer.
x Matches an optionally signed hexadecimal integer, whose format is the same as expected for the subject sequence of the strtoul function with the value 16 for the base argument. The corresponding argument shall be
a pointer to unsigned integer.
as you can read above it's optionally signed but it certainly expects a pointer to and unsigned integer
1Of course I have omitted a lot, in fact fscanf() is one of the largest sections in the standard document.