2

So i'm curious about the explanation why i'm getting different results on my code if i'm using %s on my printf section. I know the working one should use %s instead %c.

#include <stdio.h>

int main() {
    int i;
    char str1[12] = "Hello world!";
    printf("str1==%c\n", str1); 
    return 0;
}

I've tried to compile it multiple times and get some different result, sometime between: str1==�, str1==, str1== (this blank space is actually some icon this site can't display)

Blaze
  • 16,736
  • 2
  • 25
  • 44
Syauqi
  • 41
  • 6
  • 1
    `%c` is for a single char, `%s` is for a string AKA pointer to char. Google "undefined hevaviour C". – Jabberwocky Apr 29 '19 at 11:36
  • 1
    Why do you feel you need an explanation for what happens when you break your contract with the computer? If you tell it something is a `char` when it is not? Why expect useful/interesting/consistent/valid results with this? Why not simply use the correct code? – Lightness Races in Orbit Apr 29 '19 at 12:01

4 Answers4

7

str1 decays to a char* in this case. With %c you're telling printf that it's a char which it isn't. Specifying the wrong format is undefined behavior, so there's no guarantee on what happens (it could crash the program, or do worse things even). What most likely happens is that it's trying to interpret that pointer as a char, which may lead to unprintable symbols.

Blaze
  • 16,736
  • 2
  • 25
  • 44
5

Here

printf("str1==%c\n", str1);

the format specifier %c expects argument of char type but provided argument str1 is char array and it decays to char* type, compiler should have reported warning message, seems like you ignored if you could have compiled with flags like -Wall. Its good to compile code with below minimal flags like

gcc -Wall -Wextra -Werror -pedantic test.c

warning: format specifies type 'int' but the argument has type 'char *' [-Wformat]

Use %s instead of %c.

printf("str1==%s\n", str1);
alk
  • 69,737
  • 10
  • 105
  • 255
Achal
  • 11,821
  • 2
  • 15
  • 37
4

%c means character, but str1 is not a char. So you are asking printf to interpret str1 as something it is not. The result you get is not well defined when you do that.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
3

I am assuming you have a basic knowledge about pointer. If not please read about it first.

"str1" in your code is a pointer to char array and it points to the first element of the array ('H').

%c modifier is designed to take input a char value and print the ASCII representation of that value. In this case it is 'H'.

On the other hand, %s modifier is designed to work similar to the following way:

  1. take input a pointer to char
  2. make a copy of the pointer. let it be cpointer.
  3. if the value of the memory location stored in the cpointer is NULL('\0') goto 7
  4. print the value of the memory location stored in the cpointer.
  5. increment cpointer so that it point to the next element of the char array.
  6. goto 3.
  7. end printing char array.

As a result, it will print the whole string. If you are wondering about how did it found '\0' in the end of the string. it can because, when we assign some value while declaring a char array (ex: char str[] = "abc") compiler automatically adds a null character in the end. For this reason, we must specify char array size to be 1 greater than the length of the string it will store. So you declaration should have been:

char str[13] = "Hello world!";

Also when we assign a value while declaring char array, we need not specify the size of the array. It is automatically determined by the comiler. So following code will work too.

char str[] = "Hello world!";
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
priojeet priyom
  • 899
  • 9
  • 17