Rami
Rami

Reputation: 29

Printf output of pointer string explanation from an interview

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

Answers (4)

Owen
Owen

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

Vlad from Moscow
Vlad from Moscow

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

Luis Colorado
Luis Colorado

Reputation: 12668

  1. 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.

  2. 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.

  3. You are printing the passed pointer reinterpreted as a char value. Undefined behaviour, as you cannot convert a pointer to a char value.

  4. You are printing the pointed value of s as a char so you get the first character of string "12345" ('1').

  5. You are printing the next to first char pointed to by s, so you get the second character of string ('2').

  6. 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.

  7. 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

Rann Lifshitz
Rann Lifshitz

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

Related Questions