12

If I declare this:

int i = 0 + 'A';

is 'A' considered char or int?

some people might use:

int i = 0 + (int)'A';

but is this really necessary?

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
carlos
  • 1,261
  • 1
  • 12
  • 15
  • 6
    The latter is not needed. character literals are of type `int`. – WhozCraig Aug 24 '13 at 20:08
  • 2
    Even if `'A'` was of type `char`, the cast would have no effect on all but the most exotic platforms. To be precise, if `'A'` was a signed char type (either `signed char` or `char` when it is signed), there could never be any difference, and if `A` was an unsigned `char` type (either `unsigned char` or `char` when it is unsigned), then `int` and `char` would have to be the same size for a difference to be visible. – Pascal Cuoq Aug 24 '13 at 20:19
  • What is the `0 + ` good for? Even in `0 + 'A'` it serves no purpose and even less :) in `0 + (int)'A'`. – Jens Gustedt Aug 24 '13 at 20:28
  • `'A'` is a `char`, and `char` is a numeric type. It will be implicitly cast to `int` when paired with `int` on a binary operator, per standard C casting rules. – Hot Licks Aug 24 '13 at 20:34
  • http://stackoverflow.com/q/433895/62576 – Ken White Aug 24 '13 at 21:37
  • 2
    @HotLicks `'A'` is an `int`. C99 6.4.4.4:10 “An integer character constant has type int.” – Pascal Cuoq Aug 24 '13 at 22:37
  • Possible duplicate of [Why are C character literals ints instead of chars?](https://stackoverflow.com/questions/433895/why-are-c-character-literals-ints-instead-of-chars) – phuclv May 26 '17 at 02:55

3 Answers3

15

In C, character constants such as 'A' are of type int. In C++, they're of type char.

In C, the type of a character constant rarely matters. It's guaranteed to be int, but if the language were changed to make it char, most existing code would continue to work properly. (Code that explicitly refers to sizeof 'A' would change behavior, but there's not much point in writing that unless you're trying to distinguish between C and C++, and there are better and more reliable ways to do that. There are cases involving macros where sizeof 'A' might be sensible; I won't get into details here.)

In your code sample:

int i = 0 + 'A';

0 is of type int, and the two operands of + are promoted, if necessary, to a common type, so the behavior is exactly the same either way. Even this:

char A = 'A';
int i = 0 + A;

does the same thing, with A (which is of type char) being promoted to int. Expressions of type char are usually, but not always, implicitly promoted to int.

In C++, character constants are of type char -- but the same promotion rules apply. When Stroustrup designed C++, he changed the type of character constants for consistency (it's admittedly a bit surprising that A is of type int), and to enable more consistent overloading (which C doesn't support). For example, if C++ character constants were of type int, then this:

std::cout << 'A';

would print 65, the ASCII value of 'A' (unless the system uses EBCDIC); it makes more sense for it to print A.

int i = 0 + (int)'A';

The cast is unnecessary in both C and C++. In C, 'A' is already of type int, so the conversion has no effect. In C++, it's of type char, but without the cast it would be implicitly converted to int anyway.

In both C and C++, casts should be viewed with suspicion. Both languages provide implicit conversions in many contexts, and those conversions usually do the right thing. An explicit cast either overrides the implicit conversion or creates a conversion that would not otherwise take place. In many (but by no means all) cases, a cast indicates a problem that's better solved either by using a language-provided implicit conversion, or by changing a declaration so the thing being converted is of the right type in the first place.

(As Pascal Cuoq reminds me in comments, if plain char is unsigned and as wide as int, then an expression of type char will be promoted to unsigned int, not to int. This can happen only if CHAR_BIT >= 16, i.e., if the implementation has 16-bit or bigger bytes, and if sizeof (int) == 1, and if plain char is unsigned. I'm not sure that any such implementations actually exist, though I understand that C compilers for some DSPs do have CHAR_BIT > 8.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 1
    What are your references? So accurate and beautiful answer! Are you teacher? – Grijesh Chauhan Aug 24 '13 at 21:00
  • “In C++, it's of type char, but without the cast it would be implicitly converted to int” You know what I am going to say, don't you? Alright, I won't say it. – Pascal Cuoq Aug 24 '13 at 21:00
  • 1
    The MISRA C committee put their collective feet down rather had on __no implicit conversions__ and many industries now use MISRA C for quality checking. – Steve Barnes Aug 24 '13 at 21:08
  • @SteveBarnes Who is talking about a conversion here? `'A'` has type `int`. `0` has type `int`. In C++, where `'A'` has type `char`, its becoming of type `int` is a *promotion* and it is unavoidable. If you write `(int)'A'` then `'A'` is promoted to `int` before the cast. See 6.3.1.1 in the C99 standard, for instance. – Pascal Cuoq Aug 24 '13 at 21:18
  • @PascalCuoq: Your first comment: No, I don't. Your second comment: Unlike the `+` operator, a cast operator doesn't promote its argument; in C++, `(int)'A'` *does* convert the operand from `char` to `int`. (In many, but not all, contexts; the conversion would have occurred anyway; in `char c = 'A';`, there's no promotion.) – Keith Thompson Aug 24 '13 at 21:45
  • @GrijeshChauhan: No, just someone who's spent way too much time reading language standards and hanging out on Usenet. – Keith Thompson Aug 24 '13 at 21:46
  • @SteveBarnes: Avoiding implicit conversions in C or C++ would be very difficult (unless there's a compiler option to enforce it). Even `char c = 'A'` would violate the rule. – Keith Thompson Aug 24 '13 at 21:48
  • The first comment was, in reaction to “without the cast it would be implicitly converted to int”, that if `char` is unsigned and as wide as `int` (both of which appear from quick Google searches to be possible in C++), without the cast, `'A'` would not be promoted to `int` but to `unsigned int`. – Pascal Cuoq Aug 24 '13 at 21:51
  • @PascalCuoq: Ah, good point; I'll update my answer accordingly. – Keith Thompson Aug 24 '13 at 21:51
  • Regarding the second comment, I do not see the sentence “The following may be used in an expression wherever an int or unsigned int may be used” (c99 6.3.1.1:2) as having any limitation on the context. In `char c; (short)c;` `c` is promoted to `int` before being cast to `short`, not that it makes any observable difference, but it makes coding rules that pretend to banish promotions in C look quite silly. – Pascal Cuoq Aug 24 '13 at 23:16
  • 1
    You need to read the beginning of 6.3, as well as the footnote. The sentence you quoted applies only to contexts where *integer promotion* occurs. The operand of a cast is not one of those contexts. Similarly, in an assignment: `char x = ..., y = ...; x = y;`, the value of `y` is not promoted to `int` and then converted back to `char`; it's just assigned as a `char`. The point is that C doesn't require support for *arithmetic* operations on types narrower than `int`; other operations are required. – Keith Thompson Aug 24 '13 at 23:23
10

In C, 'A' type is int (not char). I think some people do int i = 0 + (int)'A'; in C++ (or make code useful in both C++/C).

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
0

According to the standard ISO C99, the type of a literal character in C is int.

However, the literal characters, like 'c', have a range that fits in a char.
Thus, you can assign a literal character to a char variable without loss of information.

 char c = 'c'; /* 'c' is int, but (c == 'c') is true */
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
pablo1977
  • 4,281
  • 1
  • 15
  • 41
  • You are confusing the question here with the other question “Why do some standard library functions return an `int` in C?”. These two questions are completely different. The answer to the question “Why do some standard library functions return an `int` in C?” involves the type `unsigned char`. Your answer does not make sense for either question. – Pascal Cuoq Aug 24 '13 at 22:59
  • I dropped the EOF paragraph. I think the rest is fine. – pablo1977 Aug 24 '13 at 23:16