9 ms·
> The C standards have the perfectly fine name "implementation dependent" to describe those things. That term is not used by the C standards. Do you mean "impl
by tom_mellior 5y ago
> The C standards have the perfectly fine name "implementation dependent" to describe those things.
That term is not used by the C standards. Do you mean "implementation-defined"? asm is not among the explicitly specified implementation-defined behaviors, it's listed under "Common extensions". I don't see any mention at all of syscalls in C99. (I'm working with http://www.dragonwins.com/courses/ECE1021/STATIC/REFERENCES/n869.pdf http://www.dragonwins.com/courses/ECE1021/STATIC/REFERENCES/... here.)
- formerly_proven 5y agoI'm not sure why syscalls would be UB; it's just not something defined by the C standard. Edit: To clarify, I meant UB in the sense it is typically used in these discussions, where the standard more-or-less explicitly says "If you do X, the behavior is undefined." Not in the literal sense of "ISO C does not say anything about write(2), hence using write(2) is undefined behavior according to the C standard", which seems like a rather tautological and useless statement to me.
- hvdijk 5y agoWhat do you think UB is if not something where the behaviour is not defined?
- tsimionescu 5y agoUB, in this context, is very explicitly used in the standard: it is undefined behavior related to a construct that the standard describes.
- hvdijk 5y ago> behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements That is literally the definition of UB from the C standard. It is explicitly also about constructs that the standard does not describe. That makes sense: the standard does not and cannot define the behaviour for any construct not in the standard, so cannot impose any requirements for such constructs, and that is all UB is: something where the standard imposes no requirements.
- tsimionescu 5y agoThe relevant discussion about UB is restricted to constructa that the standard describes. For example, writing past the end of object is UB - the construct is described in the standard, but is given no semantics by the standard. The standard does not describe pattern matching, so using pattern matching is also undefined behavior, but there is nothing to be talked about here.
- hvdijk 5y agoThe comment I replied to did talk about something not described by the standard though, namely syscalls. If you want to argue that we should not be talking about syscalls here, your issue should be with the original comment that brought them up (https://news.ycombinator.com/item?id=27222325 https://news.ycombinator.com/item?id=27222325), not with my reply, I think. However, that comment looks perfectly fine to me. Also, depending on how the syscalls are made, it actually may be explicitly described as UB by the standard, see my comment https://news.ycombinator.com/item?id=27228701 https://news.ycombinator.com/item?id=27228701 too.
- tsimionescu 5y agoSyscalls are not any more UB than any other function call, though. Whether talking about write(2) or my_foo(), the call has the semantics given by the function signature visible in the current translation unit. Sure, the C standard doesn't define what write(2)'s effects will be, but that does not mean that calling it is UB according to the standard. If the function has not been declared by the time it is first used, even then calling it is not UB - it is defined to be a compilation error (in versions earlier than C99 it was actually valid, but UB if the call did not match the actual function definition).
- hvdijk 5y ago> Sure, the C standard doesn't define what write(2)'s effects will be, but that does not mean that calling it is UB according to the standard. Yes, it does. I already explained exactly why it needs to be UB, but let me quote where the standard says so: C99 6.9 External definitions: > Semantics: > An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one. If your program provides a declaration of write() and uses it without also providing a definition, the program does not have "exactly one external definition for the identifier", it has zero definitions for the identifier. This violates a "shall" that appears outside of a constraint, for which we turn to: C99 4 Conformance: > If a "shall" or "shall not" requirement that appears outside of a constraint is violated, the behavior is undefined.
- Google234 5y agoSo is everything UB since all hardware isn’t perfect?
- hvdijk 5y agoAbout your edit: > "ISO C does not say anything about write(2), hence using write(2) is undefined behavior according to the C standard", which seems like a rather tautological and useless statement to me. That is actually not so useless at all: if you try to compile and link a program that declares and calls a function but does not define it, you will typically get a linker error about an unresolved reference. If the name matches a non-ISO C library function, however, the implementation cannot know whether your program is in error or whether you want to use that library function, and will usually accept it. For this reason, the C standard does actually make it clear that using write(2) is UB to make it clear that implementations are not required to diagnose that as an error.
- faho 5y agoSo if it is behavior that is not defined by the C standard, would that not make it undefined behavior?
- deleted 5y ago[deleted]
- colejohnson66 5y agoWhile technically correct, “undefined behavior” in terms of C and C++ refer to what the standard calls out explicitly as undefined, and not a simple “it’s not referenced, therefore it’s undefined.” For example, signed(?) integer overflow is explicitly undefined by the standard, but as @formally_proven said, just because write(2) isn’t mentioned doesn’t mean usage of it is undefined.
- _kst_ 5y agoActually, that's exactly what it means: > If a "shall" or "shall not" requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined. Undefined behavior is otherwise indicated in this International Standard by the words "undefined behavior" or by the omission of any explicit definition of behavior. There is no difference in emphasis among these three; they all describe "behavior that is undefined". write() is a function, and a call to it behaves like a function call, but the C standard says nothing about what that function does. You could have a function named "write" that writes 0xdeadbeef over the caller's stack frame. Of course if "write" is the function defined by POSIX, then POSIX defines how it behaves.
- aw1621107 5y ago> but the C standard says nothing about what that function does I'm pretty sure I'm just bad at searching through the standards document, but does the Standard actually define the precise semantics of function calls? 6.2.2 is about the function calls and the result thereof, but doesn't seem to be quite as precise about the semantics as I might expect.
- 5y ago