in C++ Primer 4th edition 2.1.1, it says "when assigning an out-of-range value to a signed type, it is up to the compiler to decide what value to assign".

I can't understand it. I mean, if you have code like "char 5 = 299", certainly the compiler will generate asm code like "mov BYTE PTR _sc$[ebp], 43"(VC) or "movb $43, -2(%ebp)"(gcc+mingw), it IS decided by the compiler.

but what if we assign a value that is given by the user input? like, via command line? and the asm code generated will be "movb %al, -1(%ebp)"(gcc+mingw) and "

mov cl, BYTE PTR _i$[ebp]
mov BYTE PTR _sc$[ebp], cl

"(VC), so now how can compiler decide what will happen? I think now it is decided by the CPU.

Can you give me a clear explanation?

+3  A: 

certainly. "Up to a compiler", in this case (Stanley Lippman's book) means "it is not forced by a standard".

The compiler does not specifically decide or necessarily generates code for handling this case. It may be platform dependent.

Pavel Radzivilovsky
+1  A: 

For most implementations, when you assign an int to a char, the compiler generates code which accesses the low-order byte of the int, and stores that in the char. In your example, the command-line input would be stored in a variable larger than char, such as int, and later assigned to char, truncating the bytes.

Heath Hunnicutt
Adding to what you said: Yes, chopping off higher bits is convenient. Most implementations probably do this. And since the resulting value depends on how signed numbers are represented (two's complement, one's complement, sign+magnitude) but no particular representation of these three is mandated, it's easy to say that the resulting value is implementation-dependent. :)
+2  A: 

certainly the compiler will generate asm code like

You are confusing the C++ language with one possible implementation on one particular platform.

I tested it under windows platform, and I just wanted to test different compilers.
+11  A: 

It is up to the compiler whether or not to let it be decided by the CPU. :)

The C++ standard specifies how your program should behave. The compiler ensures that this behavior is achieved. if you do something that is not specified by the standard, then the compiler can do anything it likes. It can produce an error message, send an email to your grandmother or hack your bank account. Or it can generate code anyway, and yes, then it's up to the CPU what happens next.

But the point is that the CPU is not responsible for ensuring that your program behaves as specified by the C++ standard. The compiler is. And so, it is up to the compiler how any deviation from the standard should be handled (even if it will often choose to do nothing special, that is still the compiler's decision)

+3  A: 

This would be an example of undefined behaviour. The C++ standard contains many sentences like this: "If (some condition), the result is undefined behaviour".

Why does undefined behaviour exist? Doesn't it just make things more complicated? Yes it does unfortunately make things more complicated for the programmer. The reason for UB is to simplify the job for the compiler writers -- either to make it easier (or possible at all!) to write the compiler in the first place, or to make it easier for the compiler to implement optimisations by making certain assumptions.

Basically, there are many rules that you are supposed to abide by when writing a C++ program. Some violations of these rules can be easily detected at compile time by the compiler, and for these the language requires the compiler to issue an error message. An example of this would be a syntax error.

But there are also violations that are difficult or impossible for the compiler to detect. An example of this would be a piece of memory that you continue using after you have called delete on it. It's actually theoretically impossible to write a program that detects every possible such violation. So rather than ask the compiler writers to solve the unsolvable problem of detecting these violations, the C++ standard simply declares that your program will experience "undefined behaviour" if you do this. Which means that you can't make any prediction of what will happen -- in fact the standard example is that UB could cause demons to fly out of your nose.

[EDIT] Actually, as litb points out, your specific case is not an example of undefined behaviour but of implementation-defined behaviour, which is slightly more civilised. :) This category describes cases where the authors of the C++ standard recognise that some sort of consistent behaviour can be reasonably expected by the programmer and is not too hard for the compiler writer to implement, but it would be onerous or counterproductive to require this behaviour to be the same on every implementation. (For example, sizeof (int) is implementation-defined -- although it's often 4 or 8, as far as the C++ standard is concerned, the only requirement is that it's >= sizeof (short).) For a compiler to claim standard conformance, it must document the specific behaviour that will occur for every scenario marked as "implementation-defined behaviour" in the standard.

+1 I feel this site has insufficient references to nasal demons :)
The Standard says the value is implementation-defined. `4.7/3`. It's undefined if the value overflows during evaluation of an operator. For the final conversion to the variable type, `4.7/3` makes an overflow yield an implementation-defined result.
Johannes Schaub - litb
Or a more low-brow view: UB is what happens when you write the functional specification *after* several programmers already wrote the code.
Hans Passant
@Hans: that doesn't make any sense.

CPUs "never" fail nor they have nothing to decide since it's impossible that they handle a out-of-range value. In the asm snippets there's no information about an out-of-range value at all, and it couldn't be otherwise once the instruction is correctly generated (and assemblers won't assemble at all if an operand does not fit the size of an operation, e.g. mov al, 123456ABh raises an error and no code is produced, since there's no an instruction that allows to load a 8bit register with a 32bit value, of course!).

The problem is all up to the compiler and standard specification. In this case, it means the standard does not mandate a exact behaviour when you try to assign a number to a variable that can't hold it... so compiler implementations "decide" what really happens.

+2  A: 

I think it's referring to a situation like this:

char c = 3456234242424 ;

3456234242424 is larger than what a signed char can hold so it will overflow. Should it then be set to the maximum positive value for char or the minimum negative value? It's not mandated in the language standard so it is up to the compiler to decide what value to assign.

Another common description of this is "implementation-dependent". The language itself does not mandate what to do, but something must be done. So the compiler, which implements the language, can/must decide.

Paul Richter