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,147 of 243,242   
   David Brown to Bart   
   Re: printf and time_t (1/2)   
   05 Feb 26 12:41:26   
   
   From: david.brown@hesbynett.no   
      
   On 04/02/2026 21:42, Bart wrote:   
   > On 04/02/2026 20:09, David Brown wrote:   
   >> On 04/02/2026 19:11, Bart wrote:   
   >>> On 04/02/2026 17:12, David Brown wrote:   
   >   
   >>>> So are you asking because you don't know what Tim's construction   
   >>>> does with these types, or because you want to know if there is a   
   >>>> portable and safe way to print out any arithmetic type, or because   
   >>>> you are perfectly aware that C's printf has limitations and you want   
   >>>> to post about how terrible C is and how great your own language is?   
   >>>>   
   >>>   
   >>> I was reponding to the example of a single variable with ONE type,   
   >>> that happens to be uint32_t, apparently a standard C type.   
   >>>   
   >>   
   >> You know perfectly well that "uint32_t" is not a standard type - it is   
   >> a typedef for a standard or extended integer type.   
   >>   
   >> And you know perfectly well that the constructions here from Tim and   
   >> Keith demonstrate safe ways to print values of type "uint32_t",   
   >> regardless of whether it is a typedef for "unsigned int", "unsigned   
   >> long int", or an extend integer type.  That was the point of their posts.   
   >   
   > And one of mine is that you might not know the type is 'uint32_t'.   
   >   
      
   Just as long as we are clear that Tim and Keith's constructs were for   
   anything other than "uint32_t", whatever its underlying type may be.   
   For other selections of types, other similar constructs are needed, as   
   appropriate.   
      
   > Even if you were 100% sure, an update might change it, and the format   
   > might no longer be appropriate. (Eg. it might become signed, but gcc   
   > will not report that, at least not with Wall + Wextra + Wpedantic.)   
      
   Again, you are talking about types other than uint32_t?  Although the   
   underlying type used for "uint32_t" is not known, its characteristics   
   are, including that it is unsigned.   
      
   Usually when you have a type T in your code, you know some things about   
   it - you typically know if it is arithmetic, integer, floating point,   
   you know something about its range.  How much you know will vary, but a   
   type you know absolutely nothing about is unlikely to be of any use in code.   
      
   >   
   >>> Yes maybe that particular strategy might work (you know it is an   
   >>> integer and that it is unsigned).   
   >>   
   >> What did you think an "uint32_t" was, if not a type of unsigned   
   >> integer?   And there is no "maybe" about it - the strategies work.   
   >   
   > See above.   
   >   
   >   
   >> If you have other arithmetic types, then you need to adapt the   
   >> strategy to fit - you need something that covers the ranges of the   
   >> data you are dealing with.   
   >>   
   >>>   
   >>> But it doesn't solve the general problem: even if there is a single   
   >>> type involved, it might be conditional or opaque (or its type is   
   >>> changed required all format codes to be revised.   
   >>>   
   >>> Or there is an expression of mixed types.   
   >>>   
   >>   
   >> There is no such thing as an "expression of mixed types".  There are   
   >> expressions formed with operators applied to subexpressions of   
   >> different types - the rules of C state very clearly how those   
   >> subexpressions are converted.  (For most binary operators, these are   
   >> the "usual arithmetic conversions".)  You know this too.   
   >   
   > An expression of mixed types means one that involves a number of   
   > different types amongst its types.   
   >   
      
   Okay, that's what /you/ mean by that phrase.  It is not an accurate   
   description - in any statically typed language, an expression will have   
   a single type.  Subexpressions can be different types.  But while I do   
   not approve of your terms here, I do understand what you are talking about.   
      
   > Sure, the rules will tell you what the result will be, but you have to   
   > work it out, and to do that, you have to know what each of those types   
   > are (again, see above).   
      
   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.   
      
   If you have "T x;", and you write "(unsigned long) x" (as Keith   
   suggested), then you know the type of that expression - without knowing   
   the type of T.  You need to know that "T" is a type that can be   
   converted to "unsigned long" (any arithmetic or pointer type will do),   
   and you need to know that the value of "x" is suitable for the   
   conversion to be defined (so if "x" is floating point, it needs to be in   
   range).  If you don't know at least that much about "x", you probably   
   should not be writing code with it.   
      
   If you write "x + 0UL" (as Tim suggested), you know the resulting type   
   if "T" is an integer type.  If T is a floating point type, however, the   
   resulting expression will have that floating point type.  And if it is a   
   pointer type, the result will have that pointer type.  On the other   
   hand, you don't have any restrictions in the values of "x".   
      
   Do you need to know the /exact/ type of an expression?  Sometimes yes,   
   sometimes no.  Since we are talking about ways to print out values   
   without knowing their exact types, clearly we don't need to know the   
   exact type here.  We need to know certain characteristics, but not all   
   details.  This is very common in coding.   
      
   >   
   > Try this one for example; T, U and V are three numeric types exported by   
   > version 2.1 of some library:   
   >   
   >     T x;   
   >     U y;   
   >     V z;   
   >     printf("%?", x + y * z);   
   >   
   > You can spend some time hunting down those types and figuring out the   
   > result type (either one of T U V or maybe W). But how confident will you   
   > be that it will still work on 2.2?   
   >   
      
   You need to know enough about the types to know how to use them for the   
   things you want to do with them.  In the real world, the names of the   
   types usually makes the basics clear.  For a library, the documentation   
   will make it clear.  So for example, the "time_t" type in the C language   
   is documented for use in functions like "mktime" and "gmtime" - but not   
   for printing out directly with printf.  You are given that it is a "real   
   type" - so you can convert it to a double and printf that, or you can   
   use functions like "gmtime" and print out the elements of the struct tm.   
      
   C is a statically typed language.  In a statically typed language, you   
   cannot have a function that can handle arbitrary types.  Languages that   
   provide a to print arbitrary types do so using methods that are not   
   supported by C - templates, overloads, type methods or helper functions   
   to convert different types to a common string format, etc.   
      
   > The change may be subtle enough that no warning is given, but enough to   
   > give a wrong result.   
      
   So make sure you know what you are doing.  Know /enough/ about the types   
   you are using, and how you can safely use them.   
      
      
   [continued in next message]   
      
   --- 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