home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c      Meh, in C you gotta define EVERYTHING      243,242 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 243,180 of 243,242   
   Kaz Kylheku to Bart   
   Re: printf and time_t   
   07 Feb 26 17:55:23   
   
   From: 046-301-5902@kylheku.com   
      
   On 2026-02-05, Bart  wrote:   
   > On 05/02/2026 22:55, Janis Papanagnou wrote:   
   >> On 2026-02-05 18:42, Bart wrote:   
   >>> On 05/02/2026 11:41, David Brown wrote:   
   >>>>   
   >>>> No, the /compiler/ has to work it out.  Whether /you/ need to work it   
   >>>> out or not, depends on what you are doing with the result.   
   >>>   
   >>> The compiler will not tell you the format codes to use!   
   >>   
   >> Well, it seems the compiler I have here does it quite verbosely...   
   >>   
   >>   
   >> $ cc -o prtfmt prtfmt.c   
   >> prtfmt.c: In function ‘main’:   
   >> prtfmt.c:8:19: warning: format ‘%d’ expects argument of type ‘int’,   
   but   
   >> argument 2 has type ‘double’ [-Wformat=]   
   >>      8 |         printf ("%d\n", f);   
   >>        |                  ~^     ~   
   >>        |                   |     |   
   >>        |                   int   double   
   >>        |                  %f   
   >> prtfmt.c:9:19: warning: format ‘%f’ expects argument of type   
   ‘double’,   
   >> but argument 2 has type ‘int’ [-Wformat=]   
   >>      9 |         printf ("%f\n", i);   
   >>        |                  ~^     ~   
   >>        |                   |     |   
   >>        |                   |     int   
   >>        |                   double   
   >>        |                  %d   
   >>   
   >>   
   >> ...giving information of every kind - here for two basic types, but   
   >> it has also the same verbose diagnostics with the '_t' types I tried   
   >> (e.g. suggesting '%ld' for a 'time_t' argument).   
   >>   
   >> Note: I'm still acknowledging the unfortunate type/formatter-coupling   
   >> notwithstanding.   
   >   
   > /Some/ compilers with /some/ options will /sometimes/ tell you when   
   > you've got it wrong.   
      
   That's an excellent reason to keep the bulk of your code portable, and   
   offer it to multiple compilers.   
      
   I think the only way you are going to run into a crappy compiler in a   
   real job situation in 2026 is if you're an embedded developer working   
   with some very proprietary processor for which the only compiler comes   
   from its vendor.  Even so the bits of your code not specific to that   
   chip can be compiled with something else. Which you want to do not just   
   for diagnostics but to be able to run unit tests on that code on a   
   regular developer machine.   
      
   > Eventually, it will compile. Until someone else builds your program,   
   > using a slightly different set of headers where certain types are   
   > defined, and then it might either give compiler messages that they have   
   > to fix, or it show wrong results.   
   >   
   > If I compile this code with 'gcc -Wall -Wextra -Wpedantic':   
   >   
   >    #include    
   >   
   >    int main() {   
   >        int a = -1;   
   >        printf("%u", a);   
   >    }   
   >   
   > it says nothing. The program displays 4294967295 instead of -1.   
      
   For that you need this:   
      
   $ gcc -Wall -pedantic -W -Wformat -Wformat-signedness printf.c   
   printf.c: In function ‘main’:   
   printf.c:5:12: warning: format ‘%u’ expects argument of type ‘unsigned   
   int’, but argument 2 has type ‘int’ [-Wformat=]   
      printf("%u", a);   
              ~^   
              %u   
      
      
   There is probably a good reason for that; passing a signed argument   
   to an unsigned conversion specifier de facto works fine, and   
   some code relies on it; i.e. the 4294967295 is what the programmer   
   wanted.   
      
   You often see that with %x, which also takes unsigned int;   
   the programmer wants -16 to come out as "FFFFFFF0", and not -10.   
      
   Someone with code like that might want to catch other problems with   
   printf calls, and not be bothered with those.   
      
   > If compile this version (using %v) using a special extension:   
   >   
   >    #include    
   >   
   >    int main() {   
   >        int a = -1;   
   >        printf("%v", a);   
   >    }   
   >   
   > it shows -1. Which is better?   
      
   Both are undefined behavior.  The latter is a documented extension   
   that works where it works, which is good.   
      
   Using %u with int /de facto/ works (and could also be a documented   
   extension).   
      
   /de facto/ is weaker than documented. But on the other hand, /de facto/   
   works in more places than %v.   
      
   If you hit a library that doesn't have %v, it doesn't work at all.   
      
   I've never seen int passed to %d or %x not work in the manner you   
   would expect if int and unsigned int arguments were passed in   
   exactly the same way and subject to a reinterpretation of the bits.   
      
   --   
   TXR Programming Language: http://nongnu.org/txr   
   Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal   
   Mastodon: @Kazinator@mstdn.ca   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca