4 ms·
C Ints are Finite Numbers
- Strilanc 13y agoOdd choice of title, given that the post is about 'isinf(someInt)' being a compile error (as opposed to treating ints as finite and returning false).
- colomon 13y agoOdd title, interesting article. Almost didn't read it, glad I did.
- IanCal 13y agoWell I suppose it probably should be. `isinf(someInt)` makes no sense to call and is most likely a logical error. Moreover, it's not defined, so you could have (pseudocode) isinf(x) if (isint(x)) return random() < 0.5 else ... I think the title makes sense, as it's about c ints being finite, and therefore nobody should be calling "isinf" with them. It was interesting that several codebases were.
- mynegation 13y agoWhile the title is true factually, it does not reflect the main point (using C11 features to improve on unsafe preprocessor constructs). I was almost tempted to say "Yeah... so?" and move on. I am glad I did not, but there are almost certainly others who did.
- gweinberg 13y agoIsn't this really an error in the spec though? Based on what the words mean, isinf and insnan logically should always return false when called with an int argument.
- simias 13y agoAs someone who write C for a living, this _Generic macro scares me a little. It looks like C++ templates using C macros, and like everything with the C preprocessor it's a hack on top of a hack. We all know the C macrolanguage has a ton of shortcomings. But adding all those weird, un-C-like behaviours just makes code harder to understand IMO. You don't expect templates in C code. I don't have anything against C++, but what's the point of C if it just becomes "like C++ but with macro hacks". If the people responsible for the C standard feel the macrolanguage needs fixing, they have all my support. But let's actually fix the language or design a new one, not add quick hacks that change the semantics of the C code for, IMO, small gains.
- Someone 13y ago<pedantic>_Generic is not a macro; it just is used a lot inside macros. You should see it as a switch on the type of its argument. This also aren't templates; you still have to write all those variants for a function, and give them unique names. More importantly, I think this is worth the hassle. Before this, you couldn't really do typedef double number_t; and then easily call functions in the standard library such as sin, acos, or pow without having to worry about the actual type of that typedef. _Generic allows library developers to hide the ugliness of having different names for similar functions. That might have been possible using preprocessor metaprogramming, but it certainly wasn't simple.
- simias 13y agoA fair point, but I think your example demonstrates what I'm worried about: for each legitimate use of this construct there will be a billion of bogus/leaky implementations that we'll have to debug in a couple of years. If I want to write "sin(a);" and let the compiler figure out which implementation of sin to use, I can already do that today. I use C++. It's a bit late to turn C into a strong-ish typed language...
- Someone 13y agoIf you accept "If I want to do X, I can already do that today. I use C++" as an argument, I don't think there is much to be done improving C. You may be able to add a header file here and there before C++ gets it, and you may be able to fix some dark corners of the language, but the big picture would be one of stagnation. Stagnation in programming languages leads to death, so you would accept that C will eventually die, with C++ being its replacement/killer. That is not necessarily a bad thing, and one could argue that it already is happening (are there still self-hosting C compilers?), but I think it is something one should realize the moment one uses that argument.
- solinent 13y agoI can imagine this happening in template code: template <typename T> bool isNumberInfinity(T number) { return isinf(number); } template <> bool isNumberInfinity(Number number) { return number == Number::INF; } So instead of specializing ints, we rely on isinf working for ints, instead of doing the "correct" thing: template <> bool isNumberInfinity(int number) { return false; } This is a very contrived since I'm using template functions, which are practically useless, but it holds for any data structure which holds a type that is meant to behave somewhat like a "number".
- pbsd 13y agoWhat do you mean by "template functions are practically useless"?
- teddyh 13y agoI thought this would be about the dangers of not checking for integer overflow. I struggled to come up with a method which, in C, safely converts a string to an integer type. I finally did it¹, but I've yet to see someone else use this method. 1) http://stackoverflow.com/a/542833/54435 http://stackoverflow.com/a/542833/54435
- com2kid 13y agoCan anyone here provide an explanation for why some code that is supposed to be high quality and trusted is calling isnan(int)? That seems to be the more pressing issue here, not the (long since done) inclusion of a new feature in C!
- rcfox 13y agoUsually, whenever there's something weird being done in C, it's because of macros or other forms of code generation. However in the case of floating point vs integers, it's also likely that a literal is missing a decimal. 1/4 != 1.0/4