Reputation: 29
I had an interview and I was given this code and asked what is the output for each one of these printf statements.
I have my answers as comments, but I am not sure about the rest.
Can anyone explain the different outputs for statements 1, 3 and 7 and why?
Thank you!
#include <stdio.h>
int main(int argc, const char * argv[]) {
char *s = "12345";
printf("%d\n", s); // 1.Outputs "3999" is this the address of the first pointer?
printf("%d\n", *s); // 2.The decimal value of the first character
printf("%c\n", s); // 3.Outputs "\237" What is this value?
printf("%c\n", *s); // 4.Outputs "1"
printf("%c\n", *(s+1)); // 5.Outputs "2"
printf("%s\n", s); // 6.Outputs "12345"
printf("%s\n", *s); // 7.I get an error, why?
return 0;
}
Upvotes: 1
Views: 705
Reputation: 919
The 7'th line is failing because a C style string is expected as an input, and you are placing a character instead.
Take a look at:
Upvotes: 1
Reputation: 310980
This call
printf("%d\n", s);
has undefined behavior because an invalid format specifier is used with a pointer.
This call
printf("%d\n", *s);
outputs the internal code (for example ASCII code) of the character '1'
.
This call
printf("%c\n", s);
has undefined behavior due to using an invalid format specifier with a pointer.
These calls
printf("%c\n", *s);
printf("%c\n", *(s+1));
are valid. The first one outputs the character '1'
and the second one outputs the character '2'
.
This call
printf("%s\n", s);
is correct and outputs the string "12345"
.
This call
printf("%s\n", *s);
is invalid because an invalid format specifier is used with an object of the type char
.
Upvotes: 5
Reputation: 12668
This code is undefined behaviour (UB). You are passing a pointer, where the function requires an int
value. For example, in a 64-bit architecture, a pointer is 64 bit, and an int
is 32 bit. You can be printing a truncated value.
You are passing the first char
value (automatically converted to an int
by the compiler) and print it in decimal. Probably you got 49
(the ASCII code for '1'
. This is legal use, but be careful about surprises, as you can get negative values if your platform char
implementation is signed
.
You are printing the passed pointer reinterpreted as a char
value. Undefined behaviour, as you cannot convert a pointer to a char
value.
You are printing the pointed value of s
as a char
so you get the first character of string "12345"
('1'
).
You are printing the next to first char
pointed to by s
, so you get the second character of string ('2'
).
You are printing the string pointed to by s
, so you get the whole string. This is legal and indeed, the common way to print a string.
You are passing the first character of string to be interpreted as a pointer to a null terminated string to be printed (which it isn't). This is undefined behaviour again. You are reinterpreting a char
value as a pointer to a null terminated string. A SIGSEGV
is common in this case, (but not warranted :) ) The signal is sent when the program tries to access unallocated memory before reaching the supposed null character that terminates the string (but it could find a '\0'
in the way and just print rubbish).
Upvotes: 1
Reputation: 4090
I used the following online C compiler in order to run your code, and here are the results:
1. 4195988 - undefined behaviour (UB), manifesting here as the address
of the char array as you stated (for a 64 bit address you might or
might not get truncation)
2. 49 - ASCII value of '1'
3. � - undefined behaviour, manifesting here as unsupported ASCII value
for a truncation of the address of the array of chars
(placing 32-bit address into a char - assuming a 32-bit system)
4. 1 - obvious
5. 2 - obvious
6. 12345 - obvious
7. Segmentation fault - undefined behaviour, trying to place the first char
of a char array into a string reserved position
(placing char into a string)
Note on point number 3: we can deduce what took place during run-time. In the specific example provided in the question -
printf("%c\n", s); // 3.Outputs "\237". What is this value?
This is a hardware/compiler/OS related behavior when handling the UB.
Why? Due to the output "\237" -> this implies truncation under the specific hardware system executing this code!
Please see the explanation below (assumption - 32-bit system):
char *s = "12345"; // Declaring a char pointer pointing to a char array
char c = s; // Placement of the pointer into a char - our UB
printf("Pointer to character array: %08x\n", s); // Get the raw bytes
printf("Pointer to character: %08x\n", c); // Get the raw bytes
printf("%c\n", s); // place the pointer as a character
// display is dependent on the ASCII value and the OS
// definitions for 128-255 ASCII values
The outputs:
Pointer to character array: 004006e4 // Classic 32-bit pointer
Pointer to character: ffffffe4 // Truncation to a signed char
// (Note signed MSB padding to 32 bit display)
� // ASCII value E4 = 228 is not displayed properly
The final printf command is equivalent to char c = s; printf("%c\n", c);
.
Why? Thanks to truncation.
An additional example with a legitimate ASCII character output:
char *fixedPointer = 0xABCD61; // Declaring a char pointer pointing to a dummy address
char c = fixedPointer; // Placement of the pointer into a char - our UB
printf("Pointer to 32-bit address: %08x\n", fixedPointer); // Get the raw bytes
printf("Pointer to character: %08x\n", c); // Get the raw bytes
printf("%c\n", fixedPointer);
And the actual outputs:
Pointer to 32-bit address: 00abcd61
Pointer to character: 00000061
a
Upvotes: 0