Reputation: 585
Here is the full code
#include<stdio.h>
int main(void) {
printf("%d", "x");
getchar();
return 0;
}
The output is 15620184. Logically is should return the numeral value of the string "x". But x itself is not a string.
Upvotes: 1
Views: 7226
Reputation: 123488
Essentially, you're attempting to print the address of the string literal "x"
as a decimal integer, which isn't guaranteed to work.
The expression "x"
has type "2-element array of char
"; since the expression is not the operand of the sizeof
or unary &
operators, it is converted ("decays") to an expression of type "pointer to char
", and the value of the expression is the address of the first character of the string.
The d
conversion specifier expects its corresponding argument to have type int
; you're passing an argument of type int *
, so the behavior is undefined. The output may be an accurate representation of the address value as a decimal integer, or it may be total garbage.
Types matter, and specific conversion specifers expect their corresponding arguments to be of a specific type (adapted from Harbison & Steele, § 15.11.7):
Output Format Specifier Argument Type
------------- --------- -------------
Decimal Integer hhi,hhd char
(Signed) hi,hd short
i,d int
li,ld long
lli,lld long long
zi,zd size_t
ti,td prtdiff_t
ji,jd intmax_t
Decimal Integer hhu char
(Unsigned) hu short
u int
lu long
llu long long
zu size_t
tu prtdiff_t
ju intmax_t
Octal Integer hho unsigned char
ho unsigned short
o unsigned int
lo unsigned long
llo unsigned long long
zo size_t
to ptrdiff_t
jo intmax_t
Hexadecimal hhx,hhX unsigned char
Integer hx,hX unsigned short
x,X unsigned int
lx,lX unsigned long
llx,llX unsigned long long
zx,zX size_t
tx,tX ptrdiff_t
jx,jX intmax_t
Decimal Float f,lf double
Lf long double
Decimal Float, e,E,le,lE double
Exponential Le,LE long double
Notation
Decimal Float, g,G,lg,lG double
Same as f or Lg,LG long double
e depending on
value
Hexadecimal a,A,la,lA double
Float La,LA long double
Single Character c int
Single Wide Character lc wint_t
String s char *
Wide String ls wchar_t *
Pointer Value p void *
Note that the representation of a pointer value is implementation-defined. Most platforms you're likely to work on will output an integral value in hex notation. Some may output the string "null" for a NULL pointer. Some may use a completely different representation.
Note that, to print a pointer value, you should explicitly cast the argument to void *
if it isn't already:
printf( "%p\n", (void *) "x" );
This is probably the only place in C where you need to explicitly cast a pointer value to void *
.
Upvotes: 2
Reputation: 30035
I want to make it clear as other have said that this code is wrong because it has undefined behavior so could do absolutely anything on your platform. Don't do this... However to aid understanding :-
"x"
is a string constant and this decays to a pointer to the string and passed as a parameter to printf
. You've asked it to print an "int" so it interprets the bytes of the address as if they were an int
and prints those.
In practice this will print the address that the string is stored at as a decimal number.
But nothing in the standard guarantees this, it could do anything, and is likely to differ on other platforms. In general though, due to the way C is implement though in most cases it will do what I've described.
Note than on some 64 bit platforms an int is 32 bits but an address is 64 bits so this is likely to at best only print an integer based on half the bytes of the address.
As others have said it's undefined and bad so don't do this, but it's still useful to understand what it's actually doing.
Edit: As suggested... If you want to interpret the data passed properly use %p
instead of %d
which tells printf
to interpret the data passed as a memory address rather than an int
. Although the format is system dependent it's likely to be print the same int
, and is properly defined behavior then
Upvotes: 9
Reputation: 10430
what does this code do? printf(“%d”, “x”);
The code will have undefined behavior. The code you have pasted will give warning. Have a look at the warning that i have got by compiling your code with gcc
.
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat=]
printf("%d", "x");
You can get to know after looking at the above warning that in place of "x"
you should pass a variable or constant of type int
but you have passed a pointer to null-terminated character array (which is "x"
). It is because you have specified a format specifier which is "%d"
in your printf function which requires a int
data type variable or constant.
Logically is should return the numeral value of the string "x"
To print the numerical value of variable of type char or character constant ('x'
), use printf as
printf("%d", 'x'): //Remeber character literal in c are stored as int
To print the character array "x"
, use printf as
printf("%s", "x"); //OR
printf("x");
To print the address stored in a pointer, you must use "%p" format specifier as
printf("%p", "x");
There are many format specifiers in c. Few are given below-
%c - For Character Variable
%d - For Integers
%f - For Double
%s - For Null-Terminated Character Array
%p - For Pointers (of void * type)
Upvotes: 4
Reputation: 53006
This code is "UNDEFINED BEHAVIOR", you should never use it, to print a string of characters you MUST use "%s"
as the specifier, to print the address stored in a pointer you MUST use "%p"
and cast the pointer to void *
, example
printf("%p\n", (void *) "x");
ALWAYS add a trailing "\n"
character to printf()
to flush the output buffer, that's only unnecessary with stderr
, but it's still good to develop the habit.
Also, "x"
IS a string, and if you want the ascii value of 'x'
the character then, this
printf("%d\n", 'x');
note the single quotes.
Please read print(3), and learn about the many specifiers handled by printf()
and family.
Upvotes: 7