5

I have a simple program like this:

#include <stdio.h>

int main(void)
{
    int numbers[] = {1, 2, 3, 4, 5};
    char chars[] = {'a', 'i'};
    char name[] = "Max";

    name[1] = chars[1];

    printf("name (before) = %s\n", name);

    name[1] = numbers[1];

    printf("name (after) = %s\n", name);

    return 0;
}

Compiling and running gives:

$ gcc -std=c11 -pedantic -Wall -Werror ex8_simple.c
$ ./a.out
$ name (before) = Mix
$ name (after) = Mx

Which is not what I want. I then dug up the question Store an integer value in a character array in C and changed the program like this:

name[1] = '0' + numbers[1];  //replacing  >> name[1] = numbers[1];

Then it works how I would expect:

$ gcc -std=c11 -pedantic -Wall -Werror ex8_simple.c
$ ./a.out
$ name (before) = Mix
$ name (after) = M2x

I don't understand whats happening under the hoods though, especially the version without '0' + … is really strange. Why is the string truncated in that "weird" way to Mx?

For reference, this is a simplified version of exercise 8 of Learn C The Hard Way.

Community
  • 1
  • 1
Max
  • 15,693
  • 14
  • 81
  • 131
  • 2
    pipe the output of the program to `hexdump -C` and look at the output. Ascii value for character `0` is `48` (dec) by adding 2 to `48` you get ascii value `50` which is the character for 2. – Fredrik Pihl May 04 '15 at 11:48
  • 1
    This is related to Ascii code. If you declare `int numbers[] = {'1',' 2', '3', '4', '5'};` then you do not need to add `'0'` . – tivn May 04 '15 at 11:52

3 Answers3

8

Each symbol has an numeric representation, so basically each char is a number. Here is the table of characters and its values.

enter image description here
(source: asciitable.com)

So, in your code name[1] = numbers[1];, you assign name[1] to 2, which is equal to symbol STX in the ASCII table above, which is not a printable character, thats why you get that incorrect output.

When you add '0' to your name[1], it is equal to add 48 to 2, so the symbol with the number 50 is '2', that's why you get that correct output.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Chan Kha Vu
  • 9,834
  • 6
  • 32
  • 64
4

Which is not what I want.

but, you've written code for that only. Let me explain both the scenario.

  • In case of

    name[1] = chars[1];
    

name[1] or a is getting replaced with chars[1] or i. So, the o/p is Mix.

  • In case of

    name[1] = numbers[1];
    

name[1] or a is getting replaced with numbers[1] or 2, (not '2'), which is non-printable.(#note) So, the output is Mx.

However, in your second approach,

 name[1] = '0' + numbers[1];

you're storing the ASCII equivalent value of '2', by adding '0'. So, the print contains the character representation of '2' in the output.

Alternative approach:

If you modify yout int array to store the decimal equivalent of char representation of digits 0-9, then you don't need to add a '0', like

int numbers[] = {'1', '2', '3', '4', '5'};

and

name[1] = numbers[1];

will give you the desired o/p.


Suggestion : Remember, array index in C is 0 based.

# NOTE : See this ASCII table for reference.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
3

In this line: name[1] = numbers[1]; , you are assigning an int value to a char name[1] , so that int value in numbers[1] is considered as the Ascii code of some char, and that char is stored in name[1].

When you do name[1] = '0' + numbers[1]; , then the number(2) is added to ascii code of the number 0, and therefore you get the actual number. The ascii code of 0 is 48, add 2 to it, you get 50, which is the ascii code for 2.

Previously, when you had assigned only name[1] = numbers[1];, without the 0, the char with ascii code 0 was printed. Since it is not a proper printable character, there was nothing displayed (in my machine it was displayed as some wierd emoticon).

Ayushi Jha
  • 4,003
  • 3
  • 26
  • 43