<p>In C there is a concept of trap representations, or non-value representations. If such a value is produced or used, immediate undefined behavior is invoked. This is one of the dangers of using uninitialized memory as there might be a trap representation.</p>
<p>However, for what reason would a language or implementation have a concept of a trap representation in the first place? Why would the behavior not be defined every one of the finite number of possible values of the finite number of bits in a type?</p>

<c><c++><undefined-behavior>
Why would a language need to have trap representations?
CC BY-SA 4.0
2023-07-10T14:08:34.037Z
Note that Itanium had a extra bit on registers to mark it as uninitialized. A C compiler would have to guarantee initialization or have the hardware trap on uninitialized register uses.
prosfilaes
CC BY-SA 4.0
2023-07-12T19:30:39.717Z
@prosfilaes - there are other examples, some of which predate the design of the C language, e.g. on the PDP-1 there is a bit in pointers that indicates that the value pointed to is another pointer that should also be dereferenced, continuing until a pointer is found without the bit set.  This means that dereferencing a pointer may cause undefined behaviour (e.g. an infinite loop) depending not only on the value of the pointer itself, but also the contents of the memory it points to.  The specification authors were clearly cautious that future hardware may also have similarly odd behaviours.
occipita
<p>One example of a where an implementation could use this is <strong>signalling NaN</strong>.</p>
<p>Some implementations have a concept of <em>'signalling NaN'</em> with unconventional behavior, such as raising a signal upon being encountered by the FPU. A concept of trap representation permits this, as a signalling NaN could just be a trap representation, whose <em>'undefined'</em> (by the C standard) behavior is defined by the implementation to raise a signal.</p>
<p><a href="https://stackoverflow.com/a/33704515/16217248">Related Stack Overflow answer</a></p>

CC BY-SA 4.0
2023-07-10T00:59:20.307Z
2023-07-10T00:59:20.307Z
CPlus
<p>If a hardware platform's largest integer type is smaller than 32 bits, and it doesn't support multi-precision arithmetic using a carry flag, the most efficient way to support the C standard's mandated larger integer types may be to leave the top bit of the lower words of each value clear, so as to allow code to easily add part of a value and determine whether it would have generated a carry out.  Addition of X2:X1:X0 to Y2:Y1:Y0 to yield result Z2:Z1:Z0 on a 16-bit platform could be done via something like:</p>
<pre><code>temp1 = X0+Y0;
temp2 = temp1 &gt;&gt; 15;
Z0 = temp1 &amp; 0x7FFF;
temp2 += X1;
temp2 += Y1;
temp1 = temp2 &gt;&gt; 16;
Z1 = temp2 &amp; 0x7FFF;
temp1 += X2;
temp1 += Y2;
Z2 = temp1;
</code></pre>
<p>Note that if bit 15 of X0, Y0, X1, or Y1 was set before performing an addition operation, that may result in the computed value being grossly wrong.</p>
<p>The Standard waives jurisdiction over how an implementation should process such cases by classifying problematic bit patterns as &quot;trap representation&quot; and waiving any jurisdiction over how implementations behave when code attempts to process them.</p>
<p>Note that the Standard's allowance for implementations that target unusual platforms handling corner cases in weird and unpredictable ways is not intended to imply that programs which are intended solely for use on more conventional platforms should not be written in ways that exploit the semantics of such platforms.  In the language the C Standard was chartered to describe, the phrase &quot;non-portable or erroneous&quot; is used, among other things, to describe actions which the Committee would have expected 99% of C implementations to process in 100% consistent fashion.</p>

CC BY-SA 4.0
2023-07-10T22:27:42.833Z
2023-07-10T22:27:42.833Z
supercat
<p>It is sometimes not possible to initialize the value to the meaningful value when variable is first declared. While some languages would conveniently put <code>0</code>, <code>null</code> or <code>false</code> for you, these values may pass as good when they are not. Some value throwing error immediately when used looks like a better candidate to initialize such fields.</p>
<p>This can also be done also with std::optional (<a href="https://en.cppreference.com/w/cpp/utility/optional/value" rel="nofollow noreferrer">.value()</a> on empty optional throws the assertion error).</p>
<p>Of course this may only be efficient enough if supported by the hardware. Checking on purpose if we are maybe operating with &quot;forbidden value&quot; every time may not be good for performance reasons.</p>

CC BY-SA 4.0
2023-07-10T07:27:40.533Z
2023-07-10T16:21:05.067Z
2023-07-10T16:21:05.067Z
Audrius Meškauskas
CC BY-SA 4.0
2023-07-10T07:36:52.790Z
[Related to this answer](https://langdev.stackexchange.com/q/481/38)
CPlus
CC BY-SA 4.0
2023-07-10T13:47:58.927Z
Audrius, that would require having code that detects undefined behaviour in every possible situation, which could be quite expensive. Maybe not in this case, but in other cases.
gnasher729
CC BY-SA 4.0
2023-07-10T14:12:55.753Z
I would disagree that "undefined behavior" is a weird concept - it is behavior that the C/C++ language specifications do not make any requirements about.  If the application, the compiler and the operating environment agree, they are perfectly free to define the behaviors themselves (and many times, especially with low level code, that sort of thing is necessary)
poncho
CC BY-SA 4.0
2023-07-11T04:05:09.983Z
@poncho: What is a weird concept is that some compiler writers insist that the Standard's waiver of jurisdiction over a construct implies a judgment that the construct is erronous rather than merely being less than 100% portable.
supercat
<h3>Because the number of bits in a type may not be well defined</h3>
<p>For most processors, operating with variables which are the processor's word length is most efficient. This maps directly onto the processor's register representation. If you have an &quot;int&quot; type which is the processor's word length though, you will get different ranges of values depending on the processor you compile for.</p>
<h3>Because &quot;safe&quot; behaviour for trap values can be unknowable by anyone but the coder</h3>
<p>Consider a state machine. If the state variable enumeration is outside the range of possible states, what should happen? Do we set the state variable back to some valid state? If so, which? Do we close the program? Reset the processor?</p>
<p>Making this &quot;undefined&quot; puts the onus onto the code author to explicitly define behaviour.</p>
<h3>Because different processors may behave differently</h3>
<p>Consider an integer at maximum, which you increment by 1. Should the value wrap around to zero, or limit at maximum? Different processors may have different opinions on that, and trying to define the behaviour in the language will make one or other processor a bad fit for the language. If this is undefined, it becomes a task for the compiler author on that processor to define it, and for the code author to handle the situation appropriately.</p>
<h3>Because hardware features can have many side effects on the processor</h3>
<p>If you write to a register which is intended to reset the processor on sending an appropriate value, the effect is clear!</p>
<h3>Because the same operation can be valid or invalid in different situations</h3>
<p>If you dereference an invalid pointer, what happens? If it's out of range of physical memory, some processors may throw an exception. Some will run perfectly normally and simply return all ones because the data bus is (normally) pulled high and no device has set a value. On an OS which manages memory, the OS will restrict pointer accesses by user programs to only addresses within their memory space - which may be virtual memory, so the process of dereferencing memory becomes yet more complex. And still for these OSes, device drivers are typically permitted to access memory which user programs cannot.</p>
<p>The range of possible operations is just too wide and too varied to define this in the language.</p>

CC BY-SA 4.0
2023-07-11T07:41:56.570Z
2023-07-11T08:34:31.293Z
2023-07-11T08:34:31.293Z
Graham
CC BY-SA 4.0
2023-07-12T13:09:35.327Z
Different implementations having different widths for `int` isn't a reason for one of the implementations to have an `int` bit-pattern that traps when you use it in addition.  A 16-bit and an 18-bit machine can each use any of the 2^16 or 2^18 possible values of `int`, assuming they're both 2's complement.  The usual reason for integer trap representations is 1's complement, where instead of being `-0` or an alternate encoding of `0`, it's invalid to have a bit pattern with all the bits set, and signed arithmetic instructions will trap on it.
Peter Cordes
CC BY-SA 4.0
2023-07-12T13:11:11.233Z
Signed integer overflow UB is separate from trap representations.  So is bad-pointer UB.
Peter Cordes
CC BY-SA 4.0
2023-07-12T21:30:53.303Z
@PeterCordes: On some platforms without anything resembling a carry flag, multi-precision arithmetic may be facilitated if code leaves a bit unused at the top of the lower words of a value, or (depending on the platform) requires that the top bit of a lower word be duplicated as the bottom bit of the word above it.  Computations with integers having invalid bit patterns may not be "trapped", but might behave unpredictably.
supercat
CC BY-SA 4.0
2023-07-12T22:23:36.677Z
@supercat: True, but that's not what this answer is claiming.  It's talking about C source that uses `int` when that's the processors register width.
Peter Cordes
CC BY-SA 4.0
2023-07-12T22:37:23.827Z
@PeterCordes: The principle could apply with `int` on a machine with e.g. a 12-bit register width and no carry flag (I don't know how the 12-bit PDP machines handled multi-precision arithmetic), and to the `unsigned` type on ones'-complement machines which may require that the upper bit be zero.
supercat
CC BY-SA 4.0
2023-07-12T22:38:40.917Z
@supercat: Yes, but again, that's not what this answer is saying.  It's saying "This maps directly onto the processor's register representation." so Graham's talking about a machine where registers are at least 16 bit, wide enough for one of them to be an `int`.
Peter Cordes
<p>One reason is hardware compatibility.  C needs to work on systems like <a href="https://devblogs.microsoft.com/oldnewthing/20150727-00/?p=90821" rel="nofollow noreferrer">Itanium</a> with its not-a-thing (NaT) bit.  Or on those that recognize invalid pointer representations (possible if the address size is different from the register size) and trap them.</p>

CC BY-SA 4.0
2023-07-10T17:14:58.603Z
2023-07-10T17:14:58.603Z
dan04
CC BY-SA 4.0
2023-07-11T07:31:02.903Z
[CHERI](https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/) is one architecture (architectural feature, strictly) in which in-memory representations of pointers may be invalid and unusable.
Toby Speight
CC BY-SA 4.0
2023-07-12T13:16:46.907Z
Invalid-pointer UB is a separate thing from trap representations in the C standard. IIRC, it's UB to even *create* a pointer that isn't pointing inside an object or to one-past-the-end, or that's misaligned.  So even pointer math on pointers that aren't to valid C objects is outside what the ISO C standard defines.  (Implementations suitable for systems programming normally do allow pointer math to work like programmers expect for treating all of RAM as an array, though.)
Peter Cordes
CC BY-SA 4.0
2023-07-12T15:28:36.643Z
@PeterCordes: The notion of "work like programmers expect" sound a bit like the maligned "DWIM" (Do What I Mean).  A better description would be that such implementations use an abstraction model in which the state of every object of type T whose address is observable is fully encapsulated at all times in the bit patterns held by of sizeof(T) bytes starting at the object's address, and avoid optimizing transforms that might deviate from that model in ways that would cause problems, and are attentive to evidence that certain transformations would be dangerous and should thus be avoided.
supercat
<p>A value is stored in a sequence of n bits. There are 2^n possible bit combinations. If the number of possible values is not a power of two then bit combinations are possible which are not legal values, and we call them trap representations.</p>
<p>For example an enum with three possible values would have to have a trap representation. You except that</p>
<pre><code>if (x == case1 || x == case2 || x == case3)
</code></pre>
<p>should always be evaluated as true, but if you somehow manage to have a different bit pattern in x, then this wouldn't or shouldn't be the case.</p>

CC BY-SA 4.0
2023-07-10T13:49:59.887Z
2023-07-10T13:49:59.887Z
gnasher729
CC BY-SA 4.0
2023-07-10T17:32:10.337Z
No, that's simply out-of-range values, which don't ordinarily cause a processor trap.
Toby Speight
CC BY-SA 4.0
2023-07-10T21:02:26.820Z
@TobySpeight A trap representation is not the same thing as a processor trap. It's an oddity of the design of C that enum types don't have trap representations (unless the underlying integer type does). Pointers in C do typically have trap representations, and you don't necessarily get a hardware trap when you try to dereference a trap representation: you might get unpredictable content or cause unpredictable effects instead if the pointer happens to contain the address of some control structures or some memory-mapped hardware.
Gilles 'SO- stop being evil'
CC BY-SA 4.0
2023-07-11T22:50:41.783Z
@Gilles'SO-stopbeingevil': On the flip side, `bool` may cause weird and nonsensical behavior if the underlying bit representation has anything other than the least-significant bit set.  For example, given `int1 = bool1; if (int1 < 2) array1[int1] = 2;` a compiler might generate code which would unconditionally store 1 to the element of `array[1]` indexed by the bottom byte of `bool1`, without testing whether it was less than 2.
supercat
CC BY-SA 4.0
2023-07-12T13:22:15.607Z
@supercat: related re: `bool` with an invalid bit-pattern: [Does the C++ standard allow for an uninitialized bool to crash a program?](https://stackoverflow.com/q/54120862) - yes, violating the ABI can lead to crashes.  Formally I'm not 100% sure whether to class this as a "trap representation" for `bool` or something else, like "uninitialized".
Peter Cordes
CC BY-SA 4.0
2023-07-12T15:20:04.997Z
@PeterCordes: Given that such a bit pattern can occur as a result of writing a `bool` object using an `unsigned char*`, and that an object whose value has been written via `unsigned char*` is not "uninitialized", I can't think of any way in which "trap representation" is less accurate than any other term I can imagine.
supercat
CC BY-SA 4.0
2023-07-12T15:34:58.030Z
@supercat: Yes, I was leaning towards "trap representation", despite it not being the CPU itself that traps on bool operations with that bit-pattern.  I guess that's a good place for C to put any object-representation that violates the ABI.
Peter Cordes
CC BY-SA 4.0
2023-07-12T15:43:26.713Z
@PeterCordes: That's precisely what "trap representation" means.
supercat
<p>Trap representations are usually a property of the underlying <strong>hardware</strong>.  If they exist, a programming language has to choose a behaviour:</p>
<ol>
<li><p>Ensure that every value is initialised to a non-trap value and that trap representations cannot be generated by user code (e.g. Java takes this approach).</p>
</li>
<li><p>Define exact results of operating on trap representations (and perhaps thereby exclude classes of hardware from being able to support the language).</p>
</li>
<li><p>Declare that the behaviour of trap representations is outside the specification of the language (e.g. C and C++).</p>
</li>
</ol>
<p>The third approach is consistent with performance-oriented languages where the overhead of (1) is unacceptable.</p>
<p>Note that in most cases, platforms are allowed to specify behaviour which the language definition leaves undefined - that can move platform-specific programs from category (3) to category (2).  In practice, that's often useful because not all programs need to be portable.</p>

CC BY-SA 4.0
2023-07-10T13:45:23.627Z
2023-07-11T07:37:28.717Z
2023-07-11T07:37:28.717Z
Toby Speight
CC BY-SA 4.0
2023-07-10T14:55:21.213Z
This has always been my understanding.
Barmar
CC BY-SA 4.0
2023-07-10T18:56:18.040Z
I agree, and must admit that I find the whole idea of having something predefined that will cause undefined behaviour if referenced somewhat troubling... in the same way that I find proofs of the non-existence of God or assertions that an arbitrary image must contain an encrypted steganographic message troubling.
Mark Morgan Lloyd
CC BY-SA 4.0
2023-07-11T18:44:13.153Z
Another reason for 3 is, C was designed to be suitable for OS kernels and device drivers, which often must do things like access absolute memory addresses.
Davislor
CC BY-SA 4.0
2023-07-11T22:57:28.163Z
@MarkMorganLloyd: The term "Undefined Behavior" means nothing more than that the Standard waives jurisdiction over a the behavior of a construct.  It does not imply judgment as to whether some ways of processing a construct might make an implication suitable for wider or narrower ranges of tasks than other ways of processing it.
supercat
CC BY-SA 4.0
2023-07-12T06:16:00.800Z
@supercat Yes, I know. But I'm uncomfortable with the idea of enumerating things that are known to result in undefined behaviour rather than enumerating things that are guaranteed to result in testable and hopefully provable behaviour.
Mark Morgan Lloyd
CC BY-SA 4.0
2023-07-12T11:24:48.620Z
@supercat "Undefined behaviour" does not just mean that the behaviour "of a construct" is undefined, but that the *entire behaviour of a program* is undefined if at least one instance of undefined behaviour occurred during execution. C compilers do perform optimizations today that are only valid if constraints hold that were inferred from "if this condition wouldn't be true, this other line in the program would have caused undefined behaviour."
Michael Karcher
CC BY-SA 4.0
2023-07-12T15:01:11.907Z
@MarkMorganLloyd: When the Standard was written, the guiding philosophy was that if 99% of implementations process a construct identically, but a few implementations might have an obvious reason why they couldn't handle it predictably, there was no need for the Standard to say anything about the behavior, since implementations would follow the commonplace behavior with or without a mandate absent a reason for doing otherwise.  See page 44 of https://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf starting at line 20 for an example documenting such expectation.
supercat
CC BY-SA 4.0
2023-07-12T15:05:04.263Z
@MichaelKarcher: If one were on a platform where unsigned arithmetic cost twice as much as signed arithmetic, but signed arithmetic overflow would cause a program execution to jump to a random location if it occurred at the same time as an I/O interrupt, having a compiler process `uint1 = ushort1*ushort2;` in a manner that would unpredictably malfunction might be more useful for some purposes than having it treat it as equivalent to the slower `uint1 = (unsigned)ushort1*ushort2;`, and users of the platform would be better qualified than the authors of the Standard to judge...
supercat
CC BY-SA 4.0
2023-07-12T15:10:10.777Z
...whether such treatment would be more or less useful *for people using that platform* than processing using unsigned semantics.  If anyone in 1989 could have anticipated that compiler writers would not only treat an expression like `ushort1*ushort2` as an invitation to optimize out constructs that would only be relevant when the product exceeds `INT_MAX`, but claim that the Standard characterizes any programs that would evaluate the expression when the product exceeds `INT_MAX` are broken, the Standard would have been soundly rejected as written.
supercat
CC BY-SA 4.0
2023-07-12T15:16:08.000Z
@MichaelKarcher: A major flaw in the notion that UB exists to facilitate optimization is that even there are many situations where a useful optimizing transform might replace one correct application behavior with an *application behavior which is *inconsistent with sequential program execution, but equally acceptable*, the Standard uses "Undefined Behavior" as a catch-all for all situations where a useful optimizing transform might cause program behavior inconsistent with sequential execution.  A fundamental principle that proponents of UB-based inferences miss is that...
supercat
CC BY-SA 4.0
2023-07-12T15:18:32.910Z
...an assumption that a program won't do X may facilitate useful optimizations *when processing programs that would have no reason to do X*, but will be at best counter-productive in cases where the most practical way of accomplishing the task at hand would be to do X.  If some tasks would involve doing X, and some wouldn't, allowing optimizers to assume that *programs which would have no reason to do X* won't do X is useful, only if one recognizes a legitimate means by which programs that would benefit from being able to do X can do so without undue impediment.
supercat
CC BY-SA 4.0
2023-07-12T17:54:03.850Z
@supercat Just to be clear, I did not mean to endorse "optimization based on undefined behaviour", I just wanted to point out that it *is performed by current compilers*, love it or hate it. So today the real world consequence of a construct having UB is no longer "the Standard waives jurisdiction over a the behavior of a construct", but it is "the Standard waives jurisdiction over a the behavior of the entire execution of the program".
Michael Karcher
CC BY-SA 4.0
2023-07-12T19:08:49.613Z
@MichaelKarcher: The Standard actually waives jurisdiction over the vast majority of practical programs: if a program does not exercise any of the translation limits given in N1570 5.2.4.1, and does not contain any `#error` directives, nothing an otherwise-conforming implementation might do with that program could render it non-conforming.  While it may be necessary for programmerss to make concessions for poor quality compilers, compilers requiring such concessions should be recognized as being inferior as a consequence.
supercat
<p>One example is that some computers would trap if an invalid bit pattern were loaded into one of the pointer registers (such as the segment selector of an 80286 protected-mode far pointer, necessary on 16-bit Windows or OS/2).  It would be difficult or impossible to detect these in advance, since user code could not examine the segment descriptor tables.  The C standards committee did not want to constrain implementations from implementing these pointers in the most efficient way.</p>

CC BY-SA 4.0
2023-07-10T05:04:45.747Z
2023-07-10T05:04:45.747Z
Davislor
# Why would a language need to have trap representations?
Posted by: username_0 on 2023-07-10
In C there is a concept of trap representations, or non-value representations. If such a value is produced or used, immediate undefined behavior is invoked. This is one of the dangers of using uninitialized memory as there might be a trap representation.

However, for what reason would a language or implementation have a concept of a trap representation in the first place? Why would the behavior not be defined every one of the finite number of possible values of the finite number of bits in a type?
**Tags:** c c++ undefined-behavior
> **Comments:**
> **username_1**: Note that Itanium had a extra bit on registers to mark it as uninitialized. A C compiler would have to guarantee initialization or have the hardware trap on uninitialized register uses.  
> **username_2**: @prosfilaes - there are other examples, some of which predate the design of the C language, e.g. on the PDP-1 there is a bit in pointers that indicates that the value pointed to is another pointer that should also be dereferenced, continuing until a pointer is found without the bit set.  This means that dereferencing a pointer may cause undefined behaviour (e.g. an infinite loop) depending not only on the value of the pointer itself, but also the contents of the memory it points to.  The specification authors were clearly cautious that future hardware may also have similarly odd behaviours.  
---
## 8 answers
### Answer by username_10 on 2023-07-10. Score: 22 | Accepted answer
Trap representations are usually a property of the underlying **hardware**. If they exist, a programming language has to choose a behaviour:

1. Ensure that every value is initialised to a non-trap value and that trap representations cannot be generated by user code (e.g. Java takes this approach).
2. Define exact results of operating on trap representations (and perhaps thereby exclude classes of hardware from being able to support the language).
3. Declare that the behaviour of trap representations is outside the specification of the language (e.g. C and C++).

The third approach is consistent with performance-oriented languages where the overhead of (1) is unacceptable.

Note that in most cases, platforms are allowed to specify behaviour which the language definition leaves undefined - that can move platform-specific programs from category (3) to category (2). In practice, that's often useful because not all programs need to be portable.
> **Comments:**
> **username_12** (2023-07-10): This has always been my understanding.  
> **username_13** (2023-07-10): I agree, and must admit that I find the whole idea of having something predefined that will cause undefined behaviour if referenced somewhat troubling... in the same way that I find proofs of the non-existence of God or assertions that an arbitrary image must contain an encrypted steganographic message troubling.  
> **username_14** (2023-07-11): Another reason for 3 is, C was designed to be suitable for OS kernels and device drivers, which often must do things like access absolute memory addresses.  
> **username_3** (2023-07-11): @MarkMorganLloyd: The term "Undefined Behavior" means nothing more than that the Standard waives jurisdiction over a the behavior of a construct.  It does not imply judgment as to whether some ways of processing a construct might make an implication suitable for wider or narrower ranges of tasks than other ways of processing it.  
> **username_13** (2023-07-12): @supercat Yes, I know. But I'm uncomfortable with the idea of enumerating things that are known to result in undefined behaviour rather than enumerating things that are guaranteed to result in testable and hopefully provable behaviour.  
> **username_15** (2023-07-12): @supercat "Undefined behaviour" does not just mean that the behaviour "of a construct" is undefined, but that the *entire behaviour of a program* is undefined if at least one instance of undefined behaviour occurred during execution. C compilers do perform optimizations today that are only valid if constraints hold that were inferred from "if this condition wouldn't be true, this other line in the program would have caused undefined behaviour."  
> **username_3** (2023-07-12): @MarkMorganLloyd: When the Standard was written, the guiding philosophy was that if 99% of implementations process a construct identically, but a few implementations might have an obvious reason why they couldn't handle it predictably, there was no need for the Standard to say anything about the behavior, since implementations would follow the commonplace behavior with or without a mandate absent a reason for doing otherwise.  See page 44 of https://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf starting at line 20 for an example documenting such expectation.  
> **username_3** (2023-07-12): @MichaelKarcher: If one were on a platform where unsigned arithmetic cost twice as much as signed arithmetic, but signed arithmetic overflow would cause a program execution to jump to a random location if it occurred at the same time as an I/O interrupt, having a compiler process `uint1 = ushort1*ushort2;` in a manner that would unpredictably malfunction might be more useful for some purposes than having it treat it as equivalent to the slower `uint1 = (unsigned)ushort1*ushort2;`, and users of the platform would be better qualified than the authors of the Standard to judge...  
> **username_3** (2023-07-12): ...whether such treatment would be more or less useful *for people using that platform* than processing using unsigned semantics.  If anyone in 1989 could have anticipated that compiler writers would not only treat an expression like `ushort1*ushort2` as an invitation to optimize out constructs that would only be relevant when the product exceeds `INT_MAX`, but claim that the Standard characterizes any programs that would evaluate the expression when the product exceeds `INT_MAX` are broken, the Standard would have been soundly rejected as written.  
> **username_3** (2023-07-12): @MichaelKarcher: A major flaw in the notion that UB exists to facilitate optimization is that even there are many situations where a useful optimizing transform might replace one correct application behavior with an *application behavior which is *inconsistent with sequential program execution, but equally acceptable*, the Standard uses "Undefined Behavior" as a catch-all for all situations where a useful optimizing transform might cause program behavior inconsistent with sequential execution.  A fundamental principle that proponents of UB-based inferences miss is that...  
> **username_3** (2023-07-12): ...an assumption that a program won't do X may facilitate useful optimizations *when processing programs that would have no reason to do X*, but will be at best counter-productive in cases where the most practical way of accomplishing the task at hand would be to do X.  If some tasks would involve doing X, and some wouldn't, allowing optimizers to assume that *programs which would have no reason to do X* won't do X is useful, only if one recognizes a legitimate means by which programs that would benefit from being able to do X can do so without undue impediment.  
> **username_15** (2023-07-12): @supercat Just to be clear, I did not mean to endorse "optimization based on undefined behaviour", I just wanted to point out that it *is performed by current compilers*, love it or hate it. So today the real world consequence of a construct having UB is no longer "the Standard waives jurisdiction over a the behavior of a construct", but it is "the Standard waives jurisdiction over a the behavior of the entire execution of the program".  
> **username_3** (2023-07-12): @MichaelKarcher: The Standard actually waives jurisdiction over the vast majority of practical programs: if a program does not exercise any of the translation limits given in N1570 5.2.4.1, and does not contain any `#error` directives, nothing an otherwise-conforming implementation might do with that program could render it non-conforming.  While it may be necessary for programmerss to make concessions for poor quality compilers, compilers requiring such concessions should be recognized as being inferior as a consequence.  
---
### Answer by username_14 on 2023-07-10. Score: 13
One example is that some computers would trap if an invalid bit pattern were loaded into one of the pointer registers (such as the segment selector of an 80286 protected-mode far pointer, necessary on 16-bit Windows or OS/2). It would be difficult or impossible to detect these in advance, since user code could not examine the segment descriptor tables. The C standards committee did not want to constrain implementations from implementing these pointers in the most efficient way.
---
### Answer by username_0 on 2023-07-10. Score: 6
One example of a where an implementation could use this is **signalling NaN**.

Some implementations have a concept of *'signalling NaN'* with unconventional behavior, such as raising a signal upon being encountered by the FPU. A concept of trap representation permits this, as a signalling NaN could just be a trap representation, whose *'undefined'* (by the C standard) behavior is defined by the implementation to raise a signal.

[Related Stack Overflow answer](https://stackoverflow.com/a/33704515/16217248)
---
### Answer by username_3 on 2023-07-10. Score: 4
If a hardware platform's largest integer type is smaller than 32 bits, and it doesn't support multi-precision arithmetic using a carry flag, the most efficient way to support the C standard's mandated larger integer types may be to leave the top bit of the lower words of each value clear, so as to allow code to easily add part of a value and determine whether it would have generated a carry out.  Addition of X2:X1:X0 to Y2:Y1:Y0 to yield result Z2:Z1:Z0 on a 16-bit platform could be done via something like:
temp1 = X0+Y0;
temp2 = temp1 >> 15;
Z0 = temp1 & 0x7FFF;
temp2 += X1;
temp2 += Y1;
temp1 = temp2 >> 16;
Z1 = temp2 & 0x7FFF;
temp1 += X2;
temp1 += Y2;
Z2 = temp1;

Note that if bit 15 of X0, Y0, X1, or Y1 was set before performing an addition operation, that may result in the computed value being grossly wrong.
The Standard waives jurisdiction over how an implementation should process such cases by classifying problematic bit patterns as "trap representation" and waiving any jurisdiction over how implementations behave when code attempts to process them.
Note that the Standard's allowance for implementations that target unusual platforms handling corner cases in weird and unpredictable ways is not intended to imply that programs which are intended solely for use on more conventional platforms should not be written in ways that exploit the semantics of such platforms.  In the language the C Standard was chartered to describe, the phrase "non-portable or erroneous" is used, among other things, to describe actions which the Committee would have expected 99% of C implementations to process in 100% consistent fashion.
---
### Answer by username_4 on 2023-07-10. Score: 4
It is sometimes not possible to initialize the value to the meaningful value when variable is first declared. While some languages would conveniently put `0`, `null` or `false` for you, these values may pass as good when they are not. Some value throwing error immediately when used looks like a better candidate to initialize such fields.

This can also be done also with std::optional ([.value()](https://en.cppreference.com/w/cpp/utility/optional/value) on empty optional throws the assertion error).

Of course this may only be efficient enough if supported by the hardware. Checking on purpose if we are maybe operating with "forbidden value" every time may not be good for performance reasons.
> **Comments:**
> **username_0** (2023-07-10): [Related to this answer](https://langdev.stackexchange.com/q/481/38)  
> **username_5** (2023-07-10): Audrius, that would require having code that detects undefined behaviour in every possible situation, which could be quite expensive. Maybe not in this case, but in other cases.  
> **username_6** (2023-07-10): I would disagree that "undefined behavior" is a weird concept - it is behavior that the C/C++ language specifications do not make any requirements about.  If the application, the compiler and the operating environment agree, they are perfectly free to define the behaviors themselves (and many times, especially with low level code, that sort of thing is necessary)  
> **username_3** (2023-07-11): @poncho: What is a weird concept is that some compiler writers insist that the Standard's waiver of jurisdiction over a construct implies a judgment that the construct is erronous rather than merely being less than 100% portable.  
---
### Answer by username_7 on 2023-07-11. Score: 4
### Because the number of bits in a type may not be well defined

For most processors, operating with variables which are the processor's word length is most efficient. This maps directly onto the processor's register representation. If you have an "int" type which is the processor's word length though, you will get different ranges of values depending on the processor you compile for.

### Because "safe" behaviour for trap values can be unknowable by anyone but the coder

Consider a state machine. If the state variable enumeration is outside the range of possible states, what should happen? Do we set the state variable back to some valid state? If so, which? Do we close the program? Reset the processor?

Making this "undefined" puts the onus onto the code author to explicitly define behaviour.

### Because different processors may behave differently

Consider an integer at maximum, which you increment by 1. Should the value wrap around to zero, or limit at maximum? Different processors may have different opinions on that, and trying to define the behaviour in the language will make one or other processor a bad fit for the language. If this is undefined, it becomes a task for the compiler author on that processor to define it, and for the code author to handle the situation appropriately.

### Because hardware features can have many side effects on the processor

If you write to a register which is intended to reset the processor on sending an appropriate value, the effect is clear!

### Because the same operation can be valid or invalid in different situations

If you dereference an invalid pointer, what happens? If it's out of range of physical memory, some processors may throw an exception. Some will run perfectly normally and simply return all ones because the data bus is (normally) pulled high and no device has set a value. On an OS which manages memory, the OS will restrict pointer accesses by user programs to only addresses within their memory space - which may be virtual memory, so the process of dereferencing memory becomes yet more complex. And still for these OSes, device drivers are typically permitted to access memory which user programs cannot.

The range of possible operations is just too wide and too varied to define this in the language.
> **Comments:**
> **username_8** (2023-07-12): Different implementations having different widths for `int` isn't a reason for one of the implementations to have an `int` bit-pattern that traps when you use it in addition.  A 16-bit and an 18-bit machine can each use any of the 2^16 or 2^18 possible values of `int`, assuming they're both 2's complement.  The usual reason for integer trap representations is 1's complement, where instead of being `-0` or an alternate encoding of `0`, it's invalid to have a bit pattern with all the bits set, and signed arithmetic instructions will trap on it.  
> **username_8** (2023-07-12): Signed integer overflow UB is separate from trap representations.  So is bad-pointer UB.  
> **username_3** (2023-07-12): @PeterCordes: On some platforms without anything resembling a carry flag, multi-precision arithmetic may be facilitated if code leaves a bit unused at the top of the lower words of a value, or (depending on the platform) requires that the top bit of a lower word be duplicated as the bottom bit of the word above it.  Computations with integers having invalid bit patterns may not be "trapped", but might behave unpredictably.  
> **username_8** (2023-07-12): @supercat: True, but that's not what this answer is claiming.  It's talking about C source that uses `int` when that's the processors register width.  
> **username_3** (2023-07-12): @PeterCordes: The principle could apply with `int` on a machine with e.g. a 12-bit register width and no carry flag (I don't know how the 12-bit PDP machines handled multi-precision arithmetic), and to the `unsigned` type on ones'-complement machines which may require that the upper bit be zero.  
> **username_8** (2023-07-12): @supercat: Yes, but again, that's not what this answer is saying.  It's saying "This maps directly onto the processor's register representation." so Graham's talking about a machine where registers are at least 16 bit, wide enough for one of them to be an `int`.  
---
### Answer by username_9 on 2023-07-10. Score: 2
One reason is hardware compatibility. C needs to work on systems like [Itanium](https://devblogs.microsoft.com/oldnewthing/20150727-00/?p=90821) with its not-a-thing (NaT) bit. Or on those that recognize invalid pointer representations (possible if the address size is different from the register size) and trap them.
> **Comments:**
> **username_10** (2023-07-11): [CHERI](https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/) is one architecture (architectural feature, strictly) in which in-memory representations of pointers may be invalid and unusable.  
> **username_8** (2023-07-12): Invalid-pointer UB is a separate thing from trap representations in the C standard. IIRC, it's UB to even *create* a pointer that isn't pointing inside an object or to one-past-the-end, or that's misaligned.  So even pointer math on pointers that aren't to valid C objects is outside what the ISO C standard defines.  (Implementations suitable for systems programming normally do allow pointer math to work like programmers expect for treating all of RAM as an array, though.)  
> **username_3** (2023-07-12): @PeterCordes: The notion of "work like programmers expect" sound a bit like the maligned "DWIM" (Do What I Mean).  A better description would be that such implementations use an abstraction model in which the state of every object of type T whose address is observable is fully encapsulated at all times in the bit patterns held by of sizeof(T) bytes starting at the object's address, and avoid optimizing transforms that might deviate from that model in ways that would cause problems, and are attentive to evidence that certain transformations would be dangerous and should thus be avoided.  
---
### Answer by username_5 on 2023-07-10. Score: 1
A value is stored in a sequence of n bits. There are 2^n possible bit combinations. If the number of possible values is not a power of two then bit combinations are possible which are not legal values, and we call them trap representations.
For example an enum with three possible values would have to have a trap representation. You except that
if (x == case1 || x == case2 || x == case3)

should always be evaluated as true, but if you somehow manage to have a different bit pattern in x, then this wouldn't or shouldn't be the case.
> **Comments:**
> **username_10** (2023-07-10): No, that's simply out-of-range values, which don't ordinarily cause a processor trap.  
> **username_11** (2023-07-10): @TobySpeight A trap representation is not the same thing as a processor trap. It's an oddity of the design of C that enum types don't have trap representations (unless the underlying integer type does). Pointers in C do typically have trap representations, and you don't necessarily get a hardware trap when you try to dereference a trap representation: you might get unpredictable content or cause unpredictable effects instead if the pointer happens to contain the address of some control structures or some memory-mapped hardware.  
> **username_3** (2023-07-11): @Gilles'SO-stopbeingevil': On the flip side, `bool` may cause weird and nonsensical behavior if the underlying bit representation has anything other than the least-significant bit set.  For example, given `int1 = bool1; if (int1 < 2) array1[int1] = 2;` a compiler might generate code which would unconditionally store 1 to the element of `array[1]` indexed by the bottom byte of `bool1`, without testing whether it was less than 2.  
> **username_8** (2023-07-12): @supercat: related re: `bool` with an invalid bit-pattern: [Does the C++ standard allow for an uninitialized bool to crash a program?](https://stackoverflow.com/q/54120862) - yes, violating the ABI can lead to crashes.  Formally I'm not 100% sure whether to class this as a "trap representation" for `bool` or something else, like "uninitialized".  
> **username_3** (2023-07-12): @PeterCordes: Given that such a bit pattern can occur as a result of writing a `bool` object using an `unsigned char*`, and that an object whose value has been written via `unsigned char*` is not "uninitialized", I can't think of any way in which "trap representation" is less accurate than any other term I can imagine.  
> **username_8** (2023-07-12): @supercat: Yes, I was leaning towards "trap representation", despite it not being the CPU itself that traps on bool operations with that bit-pattern.  I guess that's a good place for C to put any object-representation that violates the ABI.  
> **username_3** (2023-07-12): @PeterCordes: That's precisely what "trap representation" means.  
---
