Home > database >  Why does printing a char* not show the first letter?
Why does printing a char* not show the first letter?

Time:08-21

In c I have this code:

#include <stdio.h>

int main()
{
    
    char *s = "hello";
    
    printf("%c", s);
    
    return 0;
} 

However it doesn't print anything, I tried using another compiler and it printed a weird triangle like symbol.

My understanding was that it should print "h" since the s is a pointer to the first character of the string literal hello. However this is not the case, why?

CodePudding user response:

Your code has a bug which compilers can easily notice. Unfortunately many compilers accept it by default, and you need to configure the compiler to warn you about the problem. Before you do any programming in C, learn how to configure your compiler to tell you about problems. For example, with GCC or Clang, pass the options -Wall -Wextra -Werror (only remove -Werror if you want to experiment with stuff, not for what you consider to be good code).

$ gcc -Wall -Wextra -Werror a.c
a.c: In function ‘main’:
a.c:8:5: error: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Werror=format=]
     printf("%c", s);
     ^
cc1: all warnings being treated as errors

The format specified %c expects a character. C has no character type as such: char is just an integer type with a small range. All small integer types are automatically converted to int in many circumstances, including passing to variadic functions (functions that take a variable list of arguments) like printf. So printf expects an integer (int) argument here. But you're passing a variable of type char * here: a pointer to a character (s is a pointer to the first character of the string).

If you want to print the first character of the string, you need to pass the character as an argument to printf, and not a pointer to that character. So dereference that pointer.

    printf("%c", *s);

or

    printf("%c", s[0]);

The rest of this answer explains what's going on under the hood. None of this is necessary to understand how a correct C program works. This all relies on some assumptions about your system, and is not applicable to all platforms where C programs run. However, it is useful to have this background to understand what happens when you're debugging a problem with your C program.

If you let the compiler go ahead with printf("%c", s), formally, the program has undefined behavior and it can do anything. In practice, what happens on most platforms is that the value of s, i.e. the address of the string, is placed into the memory location where printf expects to read the int value for %c. So the program ends up printing one of the bytes of the address.

For comparison, try printing the address in various ways.

    printf("char: %c\n", s);
    printf("char hex: %x\n", (char) s);
    printf("int hex: %x\n", s);
    printf("full address: %p\n", s);

Here's the output I get on one particular machine:

char: x
char hex: 78
int hex: 2ab3f78
full address: 0x102ab3f78

On that particular machine, a pointer such as char* takes 8 bytes, an int takes 4 bytes, and integers are represented in little-endian format so accessing a smaller integer type at the same address gives the low-order bits of the value.

CodePudding user response:

printf with %c specifier input should be a character, not a pointer to character. a pointer is simply a number that represents where this information is stored in memory, what you see is the program trying to convert the address of the information into an ASCII character, which doesn't work very well.

instead you should pass a character to printf, which is the value pointed by your pointer, so either dereference your pointer or index into it to get the first element of the string.

printf("%c", *s);
printf("%c", s[0]);

as exception to this is when using the %s specifier which takes a pointer to null terminated array of characters, so this would print hello

printf("%s", s);
  • Related