From: Keith.S.Thompson+u@gmail.com   
      
   Tim Rentsch writes:   
   > Keith Thompson writes:   
   >> David Brown writes:   
   >> [...]   
   >>   
   >>> C23 includes length specifiers with explicit bit counts, so "%w32u" is   
   >>> for an unsigned integer argument of 32 bits:   
   >>>   
   >>> """   
   >>> wN Specifies that a following b, B, d, i, o, u, x, or X conversion   
   >>> specifier applies to an integer argument with a specific width   
   >>> where N is a positive decimal integer with no leading zeros   
   >>> (the argument will have been promoted according to the integer   
   >>> promotions, but its value shall be converted to the unpromoted   
   >>> type); or that a following n conversion specifier applies to a   
   >>> pointer to an integer type argument with a width of N bits. All   
   >>> minimum-width integer types (7.22.1.2) and exact-width integer   
   >>> types (7.22.1.1) defined in the header shall be   
   >>> supported. Other supported values of N are implementation-defined.   
   >>> """   
   >>>   
   >>> That looks to me that it would be a correct specifier for uint32_t,   
   >>   
   >> Yes, so for example this:   
   >>   
   >> uint32_t n = 42;   
   >> printf("n = %w32u\n", n);   
   >>   
   >> is correct, if I'm reading it correctly. It's also correct for   
   >> uint_least32_t, which is expected to be the same type as uint32_t   
   >> if the latter exists. There's also support for the [u]int_fastN_t   
   >> types, using for example "%wf32u" in place of "%w32u".   
   >>   
   >>> and should also be fully defined behaviour for unsigned int and   
   >>> unsigned long if these are 32 bits wide.   
   >>   
   >> No, I don't think C23 says that.   
   >   
   > Right, it doesn't.   
   >   
   >> If int and long happen to be the same   
   >> width, they are still incompatible, and there is no printf format   
   >> specifier that has defined behavior for both.   
   >>   
   >> That first sentence is a bit ambiguous   
   >>   
   >> wN Specifies that a following b, B, d, i, o, u, x, or X conversion   
   >> specifier applies to an integer argument with a specific width ...   
   >>   
   >> but I don't think it means that it must accept *any* integer type   
   >> of the specified width.   
   >   
   > As I read the standard there is no ambiguity. The first sentence   
   > says what the length modifier means. The second sentence says   
   > which types (if any) correspond to the description in the first   
   > sentence.   
      
   The descriptions for all the other length modifiers name the types   
   to which they apply in the first sentence. "hh" applies to signed   
   char or unsigned char, "l" applies to long int or unsigned long int,   
   "z" applies to size_t, and so forth. The first sentence of the   
   description for "wN" says it "applies to an integer argument with   
   a specific width".   
      
   The intent is that "%w32d" applies to an argument of type   
   int_least32_t or int32_t (if the latter exists, it must be the same   
   type as the former).   
      
   Suppose, hypothetically, that it had been the intent that "%w32d"   
   applies to *any* signed integer type with a width of 32 bits (e.g.,   
   both int and long if both are 32 bits wide). I think that the   
   current wording could express that intent. The second sentence   
   could taken as a clarification rather than a restriction. (An   
   irrelevant aside: That might actually be a nice feature.)   
      
   Assume an implementation with 32-bit int, 32-bit long, and 64-bit   
   long long, where int32_t and int64_t are int and long long,   
   respectively (e.g., "gcc -m32" with glibc on 64-bit Ubuntu), so   
   none of the intN_t types are defined as long. Then this:   
      
    printf("%w32d\n", 0L);   
      
   has undefined behavior if we assume (as I do) that "%w32d" applies   
   only to the type defined as int32_t (and int_least32_t). But the   
   0L argument *is* "an integer argument with a specific width", and   
   the following sentence "All minimum-width integer types (7.22.1.2)   
   and exact-width integer types (7.22.1.1) defined in the header   
    shall be supported." does not contradict that.   
      
   I think the phrase "an integer argument with a specific width" was   
   an attempt to describe a specific set of types, but it was worded   
   in a way that applies a larger set of types. I think the following   
   sentence is not sufficiently clear in its attempt to restrict the   
   list of applicable types.   
      
   I understand the intent. Adding a format string that can apply   
   to distinct incompatible types would be a major change that would   
   surely be discussed in greater detail. But the current wording   
   does not clearly express that intent, and one or more people here   
   have, quite understandably, interpreted the wording in a way that's   
   inconsistent with the presumed intent.   
      
   The description of wfN is a bit clearer, but could also use some   
   clarification that "a fastest minimum-width integer argument with   
   a specific width" refers specifically to the [u]int_fastN_t types.   
      
   I merely suggest a clarification, either a change in wording or   
   a footnote.   
      
   --   
   Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com   
   void Void(void) { Void(); } /* The recursive call of the void */   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|