Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.std.c Subject: Re: contradiction about the INFINITY macro Date: Thu, 30 Sep 2021 08:38:24 -0700 Organization: None to speak of Lines: 85 Message-ID: <87lf3ehy4v.fsf@nosuchdomain.example.com> References: <20210930012112$48d9@zira.vinc17.org> <87pmsqizrh.fsf@nosuchdomain.example.com> <20210930105413$d6e8@zira.vinc17.org> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: reader02.eternal-september.org; posting-host="4b075a85c80fa8b78011f466bfabf6da"; logging-data="23273"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+1sT+KX1bANSgUZrstWdJT" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cancel-Lock: sha1:Mzl65+HsOg5jrYWq6Kf65Szj6bo= sha1:c4zyby/gwrY9Ar63rH5u4p7QRXw= Xref: csiph.com comp.std.c:6325 Vincent Lefevre writes: > In article <87pmsqizrh.fsf@nosuchdomain.example.com>, > Keith Thompson wrote: >> Vincent Lefevre writes: >> > In ISO C99:TC3 to C17, 7.12p4: >> > >> > The macro INFINITY expands to a constant expression of type float >> > representing positive or unsigned infinity, if available; else to a >> > positive constant of type float that overflows at translation time. >> > >> > Consider the "else" case. It is said that INFINITY expands to a >> > constant and that it overflows, so that it is not in the range of >> > representable values of float. >> > >> > But in 6.4.4p2: >> > >> > Each constant shall have a type and the value of a constant shall >> > be in the range of representable values for its type. >> > >> > which would imply that INFINITY expands to a value in the range of >> > representable values of float, contradicted by 7.12p4. >> > >> > Same issue in the current C2x draft N2596 (7.12p7 and 6.4.4p2). > >> 6.4.4p2 is a constraint. It doesn't make it impossible to write code >> that violates that constraint. > > Yes, but the issue here is that the standard mandates the implementation > to violate a constraint, which is rather different from the case where a > user writes buggy code. No, it doesn't force the implementation to violate a constraint. It says that a *program* that uses the INFINITY macro violates a constraint (if the implementation doesn't support infinities). Constraints apply to programs, not to implementations. It means that if a program assumes that INFINITY is meaningful, and it's compiled for a target system where it isn't, a diagnostic is guaranteed. And again, it might have made more sense to say that INFINITY is not defined for such implementations (as is done for the NAN macro), but perhaps there was existing practice. Here's what the C99 Rationale says: What is INFINITY on machines that do not support infinity? It should be defined along the lines of: #define INFINITY 9e99999f, where there are enough 9s in the exponent so that the value is too large to represent as a float, hence, violates the constraint of 6.4.4 Constants. In addition, the number classification macro FP_INFINITE should not be defined. That allows an application to test for the existance of FP_INFINITE as a safe way to determine if infinity is supported; this is the feature test macro for support for infinity. The problem with this is that the standard itself doesn't say that FP_INFINITE is defined conditionally. >> If I understand correctly, it means that if an infinite value is not >> available, then a program that refers to the INFINITY macro (in a >> context where it's treated as a floating-point expression) violates that >> constraint, resulting in a required diagnostic. > > I think the consequence is more than a diagnostic (which may yield a > compilation failure in practice, BTW): AFAIK, the standard does not > give a particular definition for "overflows at translation time", > which would make it undefined behavior as usual for overflows. The meaning seems clear enough to me. It's a floating constant whose mathematical value is outside the range of float, such as 9e99999f. And yes, evaluating it (if the mandatory diagnostic does not cause compilation to fail) causes undefined behavior. I think the intent is that a portable program should check whether infinities are supported before trying to evaluate INFINITY, but that intent is not well reflected in the standard. I don't think I have access to an implementation that doesn't support infinities, so I don't know how this is handled in practice. Given the near universal adoption of IEEE floating-point, it's probably reasonably safe to assume that infinities are supported unless your program needs to be painfully portable. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips void Void(void) { Void(); } /* The recursive call of the void */