0

Program to print decimal value of a char:

#include<stdio.h>

int main(void){

  char ch = 'AB';
  printf("ch is %d\n",ch);

}

Why it is printing the decimal value of second character,why not the first character's decimal value?

Output : ch is 66

coder
  • 12,832
  • 5
  • 39
  • 53
Jaivvignesh
  • 147
  • 1
  • 2
  • 8

5 Answers5

9

Because 'AB' is a multi character constant whose value is implementation defined, whether it's 66 or not is "not predictable" in principle and in practice though predictable is not the same across different implementations.

Normally, you only use a single character in the middle of single quotes. If you use multiple characters,

  1. The compiler should warn about it.
  2. The value if the corresponding int is "not predictable" because it's implementation defined. Of course, given an implementation we hope that a multi character constant does always have the same value.

If you have used gcc, then this is what happens according to this source

The compiler evaluates a multi-character character constant a character at a time, shifting the previous value left by the number of bits per target character, and then or-ing in the bit-pattern of the new character truncated to the width of a target character. The final bit-pattern is given type int, and is therefore signed, regardless of whether single characters are signed or not. If there are more characters in the constant than would fit in the target int the compiler issues a warning, and the excess leading characters are ignored.

For example, 'ab' for a target with an 8-bit char would be interpreted as ‘(int) ((unsigned char) 'a' * 256 + (unsigned char) 'b')’, and '\234a' as ‘(int) ((unsigned char) '\234' * 256 + (unsigned char) 'a')

Community
  • 1
  • 1
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • So it is doesn't mean that it takes only the second character? – Jaivvignesh Aug 02 '17 at 13:16
  • 1
    Not at all, although we don't know the details of the implementation. But surely the reason is not that it ignores the first character and only takes the second. – Iharob Al Asimi Aug 02 '17 at 13:17
  • Thank you for helping me out. – Jaivvignesh Aug 02 '17 at 13:20
  • Disagree with "implementation defined, whether it's 66 or not is not really predictable.". It is predictable. Simple review the platform's implementation. – chux - Reinstate Monica Aug 02 '17 at 13:28
  • @chux can you detail it? – Jaivvignesh Aug 02 '17 at 13:30
  • @chux According to the standard apparently it should not necessarily be predictable [*C11 $6.4.4.4 (Character constants):*](https://stackoverflow.com/a/45462057/1983495). But of course is "*not predictable*" means that it is predictable given that you know the details about implementation, which is why I added the gcc implementation details for illustration. – Iharob Al Asimi Aug 02 '17 at 13:37
  • @IharobAlAsimi _implementation-defined behavior_ is predictable. With ID, each implementation documents how the choice is made. – chux - Reinstate Monica Aug 02 '17 at 13:52
  • @chux I think that's what I said. If you think the wording can be improved please tell me directly how so. – Iharob Al Asimi Aug 02 '17 at 13:57
  • Lets say an implementation defines the value as a random generated number... would that be a valid *implementation defined* or not? I certainly wouldn't call it *predictable*. – grek40 Aug 02 '17 at 13:59
  • @grek40 C allows for all sorts of behavior within _implementation-defined behavior_. Is random a theoretical or do you have an example of that behavior that a compiler implemented? – chux - Reinstate Monica Aug 02 '17 at 14:04
  • @chux I think "*Lets say*" means theoretical. – Iharob Al Asimi Aug 02 '17 at 14:04
  • @chux definitely theoretical... however, should I ever be bored of life I need to write a pathological C compiler that deliberately messes with all implementation defined possibilities and traps the user in a tetris game for any case of UB... – grek40 Aug 02 '17 at 14:07
  • @grek40 Even if you were to ever write such a compiler, programmers should never rely on implementation defined behavior if their code is to be portable. So your hypothetical compiler would be fun, and given it's standard compliant it will also compile useful programs. – Iharob Al Asimi Aug 02 '17 at 14:09
  • 1
    @grek40 per[this answer](https://stackoverflow.com/a/18420754/2410359), "a user reading her compiler's documentation must be given enough information to predict exactly what will happen in the specific case." So in the realm of possible and practical, random behavior would not meet the practical standard. – chux - Reinstate Monica Aug 02 '17 at 14:12
  • Per [this](https://stackoverflow.com/questions/45461862/print-decimal-value-of-a-char/45461895#comment77886483_45461895) , I would use "not specified" instead of "not predictable". Recall that `char ch = 'A'; printf("ch is %d\n",ch);` is not _specified_ to print 65. It is implementation defined behavior (ASCII). It is just that that behavior is hugely agreed on whereas `'AB'` is less consistent. – chux - Reinstate Monica Aug 02 '17 at 14:20
2
char ch = 'AB';
printf("ch is %d\n",ch); // Output "ch is 66"

Why it is printing the decimal value of second character,why not the first character's decimal value?


'AB' is an int character constant.

The value of an integer character constant containing more than one character (e.g., 'ab'), or containing a character or escape sequence that does not map to a single-byte execution character, is implementation-defined. C11 §6.4.4.4 10

Example: Your output may differ.

printf("ch is %d\n",'AB'); // prints "ch is 16706"

16706 is the same value as 0x4142 which is the concatenated value of ASCII A and B. A printout out of ch is 16961 (0x4241) or ch is 1111556096 (0x42410000) or others is possible. It is implementation defined behavior.

Assigning 16706 to an char is either implementation defined behavior or well defined - depending on if char is signed or unsigned. A common ID result is to assign the lower byte, or 0x42. `

printf("ch is %d\n", ch); // prints "ch is 66"

Assigning a value outside the char range to a char may raise a warning.

// Example warning
// warning: overflow in implicit constant conversion [-Woverflow]
char ch1 = 'AB';
char ch2 = 16706;

In addition, given the implementation defined nature of such consonant, the below may also warn:

// Example warning
// warning: multi-character character constant [-Wmultichar]
char ch1 = 'AB';

Use of multi-character character constant is limited to few select cases. So few that it is more likely a coding error that a good use.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

C11 $6.4.4.4 (Character constants):

A multi-char always resolves to an int, but that the exact value is “implementation-dependent”. That is, different compilers may resolve the same multi-char to different integers. This is a portability problem, and it is one of the reasons multi-chars are discouraged.

It means int ch = 'AB'; is ok for int type.But, If it were declared as type char, the second byte would not be retained.

So use

char ch = 'A';

instead of

char ch = 'AB';

and use %c format specifier for char type.

printf("ch is %c\n",ch);
msc
  • 33,420
  • 29
  • 119
  • 214
-1

Iharob is right. 'AB' being a multi character turns out to be not predictable. If you intend to keep the two characters 'AB', I'd recommend declaring this constant as a string char ab[] = "AB";. The print for a string could be printf("ch is %d\n", ab[0]);, to have 65 as output.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
AndyOak
  • 3
  • 3
-2
  1. First of all, this program throws a warning like

    4:12: warning: multi-character character constant [-Wmultichar]
    In function 'int main()':
    4:12: warning: overflow in implicit constant conversion [-Woverflow]
    
  2. If you know the concept of Operator precedence, will help you out why you are getting the decimal value of second character (B). In Assignment operator, precedence priority starts from Right to Left. So in this case, Right most character has more priority and stored into char ch and remaining characters are ignored.

    #include<stdio.h>
    
    int main(void){
    
    char ch = 'AB';           // Here B is assigned to 'ch' and A is ignored.
    char ch1 = 'ABCDEFG';     // Here G is assigned to 'ch1'
    
    printf("ch is %d\n",ch);
    printf("ch1 is '%c'\n",ch1);
    
    }
    

Output:

ch is 66
ch1 is 'G'

Another example using assignment operator:

    #include<stdio.h>

    int main(void){

    int a = (2,3,4,5,6);           // Here 6 is assigned to 'a' and remaining values are ignored.
    printf("a is %d\n",a);

    }

Output:

a is 6

Kindly go through the below link for operator precedence. http://en.cppreference.com/w/c/language/operator_precedence

Eswaran Pandi
  • 602
  • 6
  • 10
  • In how far is operator precedence involved if we only have a single operator? There is no coma in the multicharacter literal. – Gerhardh Aug 02 '17 at 14:01
  • "So in this case, Right most character has more priority and stored into char `ch` and remaining characters are ignored." is incorrect - yet it certainly is a novel way of thinking about character parsing and operator precedence. – chux - Reinstate Monica Aug 02 '17 at 14:43
  • **but that the exact value is “implementation-dependent”** Nothing more to say... – Gerhardh Aug 02 '17 at 15:07