views:

114

answers:

3

I didn't know that C and C++ allow multicharacter literal: not 'c' (of type int in C and char in C++), but 'tralivali' (of type int!)

enum
{
    ActionLeft = 'left',
    ActionRight = 'right',
    ActionForward = 'forward',
    ActionBackward = 'backward'
};

Standard says:

C99 6.4.4.4p10: "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."

I found they are widely used in C4 engine. But I suppose they are not safe when we are talking about platform-independend serialization. Thay can be confusing also because look like strings. So what is multicharacter literal's scope of usage, are they useful for something? Are they in C++ just for compatibility with C code? Are they considered to be a bad feature as goto operator or not?

+3  A: 

It makes it easier to pick out values in a memory dump.

Example:

enum state { waiting, running, stopped };

vs.

enum state { waiting = 'wait', running = 'run.', stopped = 'stop' };

a memory dump after the following statement:

s = stopped;

might look like:

00 00 00 03 . . . .

in the first case, vs:

73 74 6F 70 s t o p

using multicharacter literals. (of course whether it says 'stop' or 'pots' depends on byte ordering)

Ferruccio
Example, please?
topright
Ever ported your code to a Cray machine?
pmg
@pmg: Nope. I assume something bad would happen?
Ferruccio
Well, I've heard that on Cray machines, "`sizeof (char) == sizeof (int)`" is true. I have absolutely no idea what a C compiler might do to a multicharacter literal on one of those ...
pmg
+1  A: 

I don't know how extensively this is used, but "implementation-defined" is a big red-flag to me. As far as I know, this could mean that the implementation could choose to ignore your character designations and just assign normal incrementing values if it wanted. It may do something "nicer", but you can't rely on that behavior across compilers (or even compiler versions). At least "goto" has predictable (if undesirable) behavior...

That's my 2c, anyway.

Edit: on "implementation-defined":

From Bjarne Stroustrup's C++ Glossary:

implementation defined - an aspect of C++'s semantics that is defined for each implementation rather than specified in the standard for every implementation. An example is the size of an int (which must be at least 16 bits but can be longer). Avoid implementation defined behavior whenever possible. See also: undefined. TC++PL C.2.

also...

undefined - an aspect of C++'s semantics for which no reasonable behavior is required. An example is dereferencing a pointer with the value zero. Avoid undefined behavior. See also: implementation defined. TC++PL C.2.

I believe this means the comment is correct: it should at least compile, although anything beyond that is not specified. Note the advice in the definition, also.

Nick
@Nick: As far as I understand it is not allowed to fail to compile
Armen Tsirunyan
You're fine as long as you don't rely on byte ordering or try to serialize the values.
Ferruccio
I totally agree about red-flag. My interest is theoretical mostly.
topright
A: 

Four character literals, I've seen and used. They map to 4 bytes = one 32 bit word. It's very useful for debugging purposes as said above. They can be used in a switch/case statement with ints, which is nice.

This (4 Chars) is pretty standard (ie supported by GCC and VC++ at least), although results (actual values compiled) may vary from one implementation to another.

But over 4 chars? I wouldn't use.

UPDATE: From the C4 page: "For our simple actions, we'll just provide an enumeration of some values, which is done in C4 by specifying four-character constants". So they are using 4 chars literals, as was my case.

jv42
Ever ported your code to a Cray machine?
pmg
Nope, didn't encounter one of these beast. Code I've used was for x86-32 bits Windows PC.
jv42