5 ms·
This is undefined behavior, so you're claim that this is 'in C' is blatantly false. In general, you cannot assume the underlying architecture will pass its argu
by tathougies 10y ago
This is undefined behavior, so you're claim that this is 'in C' is blatantly false. In general, you cannot assume the underlying architecture will pass its arguments in any particular location.
- catnaroek 10y agoThe problem is that determining whether an ostensibly C (syntactically valid and typable) program is actually written “in C” is undecidable.
- adrianN 10y agoAlmost any interesting property about programs is undecidable. Yet somehow programmers still write nontrivial programs. Undefined behavior in C sucks, but being its presence or absence being undecidable is not the main reason.
- catnaroek 10y ago> Almost any interesting property about programs is undecidable. It's only undecidable if the language makes it undecidable. For example, subject reduction is decidable in a type-safe language (EDIT: with decidable type checking, oops!), because the very definition of type safety means that typability implies subject reduction. Of course, not everything of interest can be made decidable in a general-purpose language, but the integrity of a language's basic abstractions should never be in question.
- haldean 10y agoThe formalization of this idea is Rice's Theorem: https://en.wikipedia.org/wiki/Rice%27s_theorem https://en.wikipedia.org/wiki/Rice%27s_theorem
- catnaroek 10y agoRice's theorem is a statement about partial functions, not programs. There exist decidable properties of programs: Is it of size less than N (for any suitable measure)? Does it finish in less than N steps (for a given fixed input)? Two syntactically distinct programs may compute the same partial function.
- dllthomas 10y agoCareful about what you're quantifying over. Any interesting property is undecidable in the sense that we will be unable to produce an answer for some programs. Nothing says that there can't exist plenty of nontrivial programs for which we can show the property holds.
- taneq 10y agoExcellent point. This misconception is also the root of silly statements like "human intelligence is uncomputable because we can do things like tell whether a program will halt." No, we can solve specific cases of the halting problem, we can't solve the general case any more than a computer can.
- dllthomas 10y ago> we can't solve the general case any more than a computer can While almost certainly the case, I'm not sure how we can demonstrate that this is true in principle without begging the question, if we're asking whether human intelligence is computable. I agree that all we have evidence of is that we can solve specific cases, and that this completely undermines the argument you're critiquing. This error also occurs more subtly. I had someone tell me that static type checking was basically useless because it couldn't even do something as simple as saying whether a program will halt. Nevermind, if we're demanding this of all programs, that neither can any other method of reasoning we're applying. (And also nevermind, if we're demanding this of an interesting subset of programs, that there are type systems that will tell us exactly that...).
- adrianN 10y agoJust like there are plenty of nontrivial C programs where we can be sure that the behavior is defined. That's exactly my point.
- kbenson 10y agoIt's specifically presented as not part of C. I cheated a little bit above — I assumed you're running code on a 64-bit x86 PC. If you're on another architecture, the trick above might not work. In spite of C's reputation for having an infinite number of dark corners, the int-double-argument-order behavior is certainly not a part of the C standard. It's a result of how functions are called on today's x86 machines, and can be used for some neat programming tricks.
- twoodfin 10y agoBut it is part of the C standard: It's explicitly undefined behavior. There are varieties of type punning that are legal C, so I agree it's confusing to present this UB implementation artifact as "Type Punning ... in C". Still a neat magic trick, and an interesting explanation of how it works.
- kbenson 10y agoIn that respect, every possible situation that could happen is part of the standard, as it separates everything into defined and undefined. Cosmic rays twiddling bits in memory is part of the standard by UB under that view. While technically correct, it's useless in practice when taken to this extreme.
- scott_s 10y agotwoodfin is correct in saying that it is explicitly undefined behavior: "If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined." See http://stackoverflow.com/questions/188839/function-pointer-cast-to-different-signature http://stackoverflow.com/questions/188839/function-pointer-c... Your response would make sense if twoodfin claimed it was implicitly undefined behavior. But that's not the case. The standard clearly addresses this case.
- kbenson 10y agoWell, if it relied on just that then that would be accurate. It also relies on the specific architecture and registers available and the calling conventions of the target format (which use different numbers of registers for function arguments).
- coldtea 10y ago>This is undefined behavior, so you're claim that this is 'in C' is blatantly false. Undefined behavior is undefined behavior FOR C. Undefined behavior makes no sense unless referring to a specific language. Besides, people have been taking advantage of certain undefined behaviors in actual C programs since the dawn of time -- deliberately I mean.
- quotemstr 10y agoIt's important to note that standards other than C can place constraints on C implementations and make things that are "undefined" according to ANSI C perfectly valid in specific environments. For example, POSIX now mandates that the NULL pointer has all zero bits: http://austingroupbugs.net/view.php?id=940 http://austingroupbugs.net/view.php?id=940
- wahern 10y agoThe representation of types is either unspecified or implementation-defined in C, depending on the context. See C11 6.2.6; also see Annex J. Relying on particular representations does not make your program per se invalid C. Reliance on undefined behavior does make it invalid. Representations are readily observable because the standard permits all objects to be cast to char type. Therefore the standard basically says that you can read and even modify objects through a char array as long as you obey house rules. So POSIX isn't changing what undefined means by mandating that CHAR_BIT is 8, or that null pointers can be represented as all-zero bits. By contrast, I think the definition of dlsym() does depend on undefined behavior because C does not permit casting function pointers to void pointers or vice-versa. For various reasons that's a significant deficiency. Keeping that behavior undefined is intended to, among other things, preserve the ability to implement tagged pointers in a standards compliant manner, or to even create implementations for Harvard architecture machines. Also, I think the distinction between undefined behavior and unspecified or implementation-defined behavior preserves the ability to implement practical, quality static analyzers that can analyze all C code, whether or not dependent on certain implementation-specific behaviors. Some amount of license is a practical necessity; too much makes the standard useless. C permits assignment of pointers to functions of incompatible types as long as the functions aren't invoked. But mixing pointers to functions and pointers to objects is a definite no-no. So POSIX will probably add a sister to dlsym that returns a generic function pointer type like (void (*)(void)).
- rbanffy 10y agoI wonder whether it'd be feasible to have the compiler issue warnings for explicitly undefined behavior. While this is not something you'd self-inflict by accident, other more subtle traps could be flagged. I have known of organizations that are happy only when code compiles without warnings.
- qwertyuiop924 10y agoCode with UB is valid C. Nasal Demons and all. Otherwise, it would be illegal to do this: int i = 16 >> 32;
- _pmf_ 10y agoC guarantees some properties. The platform ABI is guaranteed to work in a certain way. In this specific case, the compiler is not allowed to make any assumptions about the legality, but has to follow the ABI. There's no UB involved (not every platform specific issue may be labeled UB; think accessing bare metal memory on one platform where a specific address is IO mapped and on another it is regular SRAM; it's perfectly valid C, and has perfectly known semantics on both platforms, but will work on one platform and not work on another platform; this is also not UB).
- yoklov 10y agoNope, it's UB[0]. While not everything that doesn't work on every platform is UB, plenty of things are. Consider signed integer overflow, which is a common source of UB. To be clear, UB means the compiler is allowed to e.g. totally remove the call (or really anything else it wants to do at all) if it can be positive that this is what's happening -- not that it will behave as could be expected on the platform, the term for that would be implementation defined behavior. [0]: http://c0x.coding-guidelines.com/6.3.2.3.html http://c0x.coding-guidelines.com/6.3.2.3.html number 766-768
- _pmf_ 10y agoYou're right.