4 ms·
As someone who was on X3J11 at the time C89 was ratified, I can tell you that supporting 1s-compliment architectures was necessary. The standard would not have
by rootbear 8y ago
As someone who was on X3J11 at the time C89 was ratified, I can tell you that supporting 1s-compliment architectures was necessary. The standard would not have been approved if 2s-compliment had been mandated. Standards are all about compromise, even when you know that that will cause trouble later.
- ropeadopepope 8y ago> I can tell you that supporting 1s-compliment architectures was necessary Can you elaborate on that point? Why was it necessary then, but not still necessary now?
- rootbear 8y agoSorry, I didn't mean to imply that there are no 1s-compliment systems still around. The comment I was replying to suggested it was a mistake to support 1s-compliment architectures because that was the source of some of the Undefined Behavior (UB) that so troubles C. My point was that not supporting 1s-compliment wasn't an option then (and probably is not one now.) After all, without 1s-compliment support, how could I write new C apps for the Apollo Guidance Computer? I would like to give an example of how supporting both 1s- and 2s-compliment is the source of a specific UB, but I can't take the time to do that right now, regrettably. Similarly, supporting both Big Endian and Little Endian was necessary. As was supporting ASCII, EBCDIC, and probably Fieldata and five level Baudot (looking at you, trigraphs). All of this generality made it hard to say anything useful in some areas, so you end up in some cases just calling it Undefined, since there was no consensus on how it should be defined.
- jonny_eh 8y agoI suppose you both can be right. It could have been required to support 1s-compliment systems at the time, but also an unfortunate mistake in retrospect.
- insulanus 8y agoWhen issues like this come up, I think the right outcome is to support the popular choice as the default, and support the unpopular choice, but with a penalty. For example, forcing extra code to be inserted, that is, a check (or even a call out to a library), so one unified semantic is followed, and there is no undefined behaviour. Of course, you wouldn't mandate how the semantics are followed. The problem is, it was very hard for us to accept this kind of solution when we grew up feeling like every cycle counted, so that's what I blame for a lot of the UB we see today in the standard.
- makomk 8y agoIf I remember correctly, one of the things that's likely changing in the next version of the C standard is that arithmetic will be required to be 2s-compliment. There just aren't enough machines around which use anything else anymore.
- loup-vaillant 8y ago> All of this generality made it hard to say anything useful in some areas, so you end up in some cases just calling it Undefined, since there was no consensus on how it should be defined. This is a very valid justification of implementation defined. Maybe even unspecified. But undefined? How could you justify that? Even if some platform does not support something at all, and goes bananas whenever you do it (say, signed overflow that traps), what would stopped the standard to say that whether the stuff is undefined or not is platform dependent? Perhaps the committee didn't anticipate how unreasonable compiler writers turned out to be?
- rootbear 8y agoI agree that you want as few UBs as possible. I found the text below from the Rationale useful for understanding these issues. An important feature of UB is that it doesn't require the compiler to catch certain things that can be very hard to catch, such as dereferencing NULL pointers. As noted, it also provides opportunities for enhancing the language in ways that don't break conforming programs. An implementation is allowed to treat Undefined Behavior as Implementation Defined, simply be saying what the implementation does in such cases. But it's not required to say what it does. ---- The terms unspecified behavior, undefined behavior, and implementation-defined behavior are used to categorize the result of writing programs whose properties the Standard does not, or cannot, completely describe. The goal of adopting this categorization is to allow a certain variety among implementations which permits quality of implementation to be an active force in the marketplace as well as to allow certain popular extensions, without removing the cachet of conformance to the Standard. Appendix F to the Standard catalogs those behaviors which fall into one of these three categories. Unspecified behavior gives the implementor some latitude in translating programs. This latitude does not extend as far as failing to translate the program. Undefined behavior gives the implementor license not to catch certain program errors that are difficult to diagnose. It also identifies areas of possible conforming language extension: the implementor may augment the language by providing a definition of the officially undefined behavior. Implementation-defined behavior gives an implementor the freedom to choose the appropriate approach, but requires that this choice be explained to the user. Behaviors designated as implementation-defined are generally those in which a user could make meaningful coding decisions based on the implementation definition. Implementors should bear in mind this criterion when deciding how extensive an implementation definition ought to be. As with unspecified behavior, simply failing to translate the source containing the implementation-defined behavior is not an adequate response.
- xorblurb 8y agoCould have been (should, in some -most?- cases) implementation defined.