[HN Gopher] Truthiness in C
       ___________________________________________________________________
        
       Truthiness in C
        
       Author : todsacerdoti
       Score  : 65 points
       Date   : 2023-09-15 13:04 UTC (9 hours ago)
        
 (HTM) web link (dxuuu.xyz)
 (TXT) w3m dump (dxuuu.xyz)
        
       | thesnide wrote:
       | Navigating down the hyperlinks rabbit hole, I discovered native
       | BCD asm instructions im x86
       | 
       | https://www.felixcloutier.com/x86/aam
       | 
       | Who said that curiousity was bad?
        
         | recursive wrote:
         | No one said that.
        
           | zengid wrote:
           | It killed the cat.
        
             | D-Coder wrote:
             | What did the cat want to know?
        
             | irq wrote:
             | That cat had one hell of a life before it died though.
        
               | giomasce wrote:
               | If it had to deal with BCD it was a hell indeed...
        
       | jonny_eh wrote:
       | Try int -> bool -> int
        
       | stefanos82 wrote:
       | If I'm not mistaken, the `(bool)` is unnecessary due to how
       | implicit conversion works: `In a return statement, the value of
       | the operand of return is converted to an object having the return
       | type of the function` [1] ...unless I understood it incorrectly
       | :/
       | 
       | [1] https://en.cppreference.com/w/c/language/conversion
        
         | swinglock wrote:
         | That's correct.
        
       | projektfu wrote:
       | so                  return (bool)x;
       | 
       | is equivalent to                  return 0!=x;
       | 
       | and                  return !!x;
       | 
       | https://godbolt.org/z/Gq5j8j66a
       | 
       | Sorry, this is the C link:
       | 
       | https://godbolt.org/z/crxecb9c3
        
       | colesbury wrote:
       | This misses the fact that signed integer promotions are generally
       | _not_ free because they require sign extension. For example, the
       | cast in b() emits a `movsx` (move with sign-extension). `movsx`
       | is not free in the ways that `mov` can be.
       | 
       | `mov` can be "free" in two ways:
       | 
       | - the compiler can frequently avoid emitting the `mov` when part
       | of a larger operation
       | 
       | - modern CPUs handle `mov` instructions earlier in the pipeline
       | 
       | Neither of those are true for `movsx`.
        
       | marcosdumay wrote:
       | Yeah, C now has bool natively...
       | 
       | I'm quite confident the compiler will optimize that test-and-move
       | away as soon as you use the bool for something, giving you the
       | same assembly as a last century's `typedef bool int`.
        
         | _kst_ wrote:
         | C has had _Bool natively since the 1999 ISO standard (24 years
         | ago). The standard header <stdbool.h> has "#define bool _Bool".
         | (The ugly name "_Bool" was chosen to avoid conflicting with
         | existing code.)
         | 
         | The upcoming C23 standard will define "bool" as a keyword.
        
           | kevin_thibedeau wrote:
           | More significantly, true and false are now keywords.
        
         | danobi wrote:
         | I think it has to keep it for externally visible functions,
         | right?
        
           | marcosdumay wrote:
           | Yes, you are right. If you have to put a bool on the stack,
           | it will have to keep the instructions.
        
         | strkitten wrote:
         | Did you mean `typedef int bool`?
        
           | _kst_ wrote:
           | No, _Bool is a distinct type, introduced by the 1999 edition
           | of the standard.
        
             | Longhanks wrote:
             | No, marcosdumay wrote 'typedef bool int', by which he/she
             | probably meant 'typedef int bool', which was not so
             | uncommon when there was no native bool type in C, since the
             | former would be illegal since the standard forbids
             | typedefing already existent types such as int. strkitten
             | informed about the probable typo.
        
               | _kst_ wrote:
               | Sorry, I managed to miss the context.
        
           | [deleted]
        
       | thxg wrote:
       | The article is very recent (September 2023 [1]), mentions that
       | "rax is used to return integer values" in the SysV ABI (hence
       | implicitly the 64-bit SysV ABI). Also confirmed in this excerpt:
       | 
       | > Note that the top 56 bits in rax are not zeroed - they contain
       | junk. This is fine b/c the compiler will only make callers check
       | the lowest bit of a register for boolean operations. This is why
       | changing the compiler's "understanding" (ie the cast) is
       | necessary.
       | 
       | ... and yet, the function ABI is clearly i386 (fetching arguments
       | from stack) and indeed everything is compiled with -m32 [2] (i.e.
       | 32-bit SysV ABI). This is a strange contradiction in 2023. On the
       | Intel/AMD side, x86_64 has been prevalent (and the default)
       | for... more than 15 years?
       | 
       | It does not invalidate the article's point. But it is slightly
       | confusing....
       | 
       | [1] https://dxuuu.xyz/
       | 
       | [2] https://godbolt.org/z/ff8r44nKn
        
         | AshamedCaptain wrote:
         | The article has too many x86 assumptions. The casts are most
         | definitely _not_ free, because there are multiple operations
         | like sign-extending, zero-extending, etc. which depend on the
         | ABI. The fact that these are all almost free in x86 is
         | irrelevant since some architectures will have to go out of
         | their way to implement the operation (albeit the ABI is usually
         | designed to make these operations simple). Similarly, I could
         | also imagine another architecture having a shorter instruction
         | to set a register to 0/1, or even one where _Bool is defined
         | with the machine word size and thus doesn't need any cast
         | whatsoever (not even sign extension).
         | 
         | On such architecture "casting to bool" would be free, but
         | other, narrowing type conversions would not.
        
           | danobi wrote:
           | Above two comments are very helpful, thanks. I've corrected
           | the -m32 issue.
           | 
           | And thanks for pointing out the x86/ABI assumptions. Had not
           | considered that. It's certainly interesting to think about.
        
       ___________________________________________________________________
       (page generated 2023-09-15 23:01 UTC)