8000 does not work for extended or bit-precise integer types · Issue #4 · rcseacord/cmp_int · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

does not work for extended or bit-precise integer types #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
gustedt opened this issue Nov 9, 2021 · 3 comments
Open

does not work for extended or bit-precise integer types #4

gustedt opened this issue Nov 9, 2021 · 3 comments
Labels
enhancement New feature or request

Comments

@gustedt
Copy link
gustedt commented Nov 9, 2021

The case listing in the macros is quite restrictive. I think better would be something like

#define is_signed(X)    \
_Generic((X),               \
   bool: 0,                    \
   char: (char)-1 < 0,    \
   signed char: 1,         \
   signed short 1,         \
   unsigned char: 0,    \
   unsigned short: 0,   \
   default: (0 ? (X)%1 : -1) < 0 \
)

That ensures to work also for __int128 or other such wild animals if they exist, and to give the expected answer for char if the user has a concept of "could hold negative values" for being a signed type.

@AaronBallman AaronBallman added the enhancement New feature or request label Nov 9, 2021
@gustedt
Copy link
Author
gustedt commented Nov 9, 2021

The %1 trick also ensures that this targets exactly integer types, for all others this expression is a constraint violation. So there would be no need of the static_assert part.

@rcseacord
Copy link
Owner

I tried the following:

#define is_signed(x)  (_Generic((x),  \
   _Bool: 0,   \
   char: (char)-1 < 0,    \
   signed char: 1,         \
   signed short: 1,         \
   unsigned char: 0,    \
   unsigned short: 0,   \
   default: (0 ? (x) % 1 : -1) < 0))

Unfortunately this breaks down for the following test cases:

puts(cmp_equal(-5, (unsigned)5) ? "true" : "false");

Casting the value to unsigned generates all sorts of compiler warnings:

<source>: In function 'main':
<source>:52:28: warning: operand of '?:' changes signedness from 'int' to 'unsigned int' due to unsignedness of other operand [-Wsign-compare]
   52 |    default: (0 ? (x) % 1 : -1) < 0))
      |                            ^~
<source>:92:24: note: in expansion of macro 'is_signed'
   92 |     (is_signed(lhs) == is_signed(rhs) ? (lhs) == (rhs) : \
      |                        ^~~~~~~~~
<source>:125:10: note: in expansion of macro 'cmp_equal'
  125 |     puts(cmp_equal(-5, (unsigned)5) ? "true" : "false");
      |          ^~~~~~~~~
<source>:52:32: warning: comparison of unsigned expression in '< 0' is always false [-Wtype-limits]
   52 |    default: (0 ? (x) % 1 : -1) < 0))
      |                                ^
<source>:92:24: note: in expansion of macro 'is_signed'
   92 |     (is_signed(lhs) == is_signed(rhs) ? (lhs) == (rhs) : \
      |                        ^~~~~~~~~
<source>:125:10: note: in expansion of macro 'cmp_equal'
  125 |     puts(cmp_equal(-5, (unsigned)5) ? "true" : "false");
      |          ^~~~~~~~~
Compiler returned: 0

or any unsigned type:

    unsigned int ui = 5; 
    puts(cmp_equal(-5, ui) ? "true" : "false");

@gustedt
Copy link
Author
gustedt commented Nov 10, 2021

ah, what a crap ;-)
I usually avoid to switch this kind of warning on, because I use unsigned types as they are supposed to be.
You may get away with this by introducing an extra macro for readability

#define __convertto(X, C) (0 ? (X) : (C))

that you then only use with non-negative constants
the default expression then becomes

((-__convertto(X, 1)) < __convertto(X, 0))

The warning for "always false" is even crappier. That kind of warning is really not constructive if you are doing macro programming.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants
0