Earlier quoted context omitted.
Singed integers in C do not implement modular arithmetic. You can trust me on this.
I'd trust you a lot more if you actually pointed out something wrong with my statement.
Unsigned sizes: A five year mistake
141–150 of 153 posts
Re: Unsigned sizes: A five year mistake
#142Earlier quoted context omitted.
#include unsigned int pack_rgb(unsigned char r, unsigned char g, unsigned char b) { return (r Compiler Explorer link, https://godbolt.org/z/3jExdaTT9 I would expect a better comment from someone working on the standard.
You should know that the type is promoted to int first, which is also what makes your example work. This is what happens when you perform the computation using an non-promoting 8 bit unsigned type: https://godbolt.org/z/fxxva4nWq
Re: Unsigned sizes: A five year mistake
#143Earlier quoted context omitted.
I'd trust you a lot more if you actually pointed out something wrong with my statement.
It is wrong that signed types in C implement modular arithmetic. They have undefined behavior on overflow.
Re: Unsigned sizes: A five year mistake
#144Using signed sizes adds a lot of footguns and performance degradations and in exchange gives only small code simplifications in rare and niche cases.
Re: Unsigned sizes: A five year mistake
#145Earlier quoted context omitted.
I am not convinced. A byte is for low-level accessing of memory, you shouldn't really do any computation with it, except maybe low-level bit-fiddling or crypto, but then the non-wrapping non-negative inter is not correct either. Natural numbers are nice, but then we invented zero and negative number so we got a group structure for addition which is really useful. Because even for a counter, or some index, you may wan…
Was this last part added or did I just miss it? Huh. > And the rust design with unsigned type where subtraction does not return a signed type but may fail at return or silently produce the wrong results, seems the worst possible design imaginable to me. You can ask for whatever you meant, and indeed asking for what you meant is crucial here because if we express ourselves we get the desired results. For example u8::b…
C has a single '+' operator, just like Rust has. And what that operator does depends on the types to the left and to the right. You can cast between integer types to achieve different behaviours depending on what you want.
About u8::unchecked_sub() etc, those are just regular functions. Not really a language thing. Yes, nothing of that is standardized in C AFAIK, but I'll happily use e.g. __builtin_add_overflow() or whatever in practice.
We can argue all day long what are the right defaults, checked or unchecked operations. If you want to be safe, you want the compiler to emit checks. It's probably possible to get some of those in GCC. If you want to emit streamlined machine code, you'll definitely not want to add checks after every machine instruction.
Re: Unsigned sizes: A five year mistake
#146Earlier quoted context omitted.
Was this last part added or did I just miss it? Huh. > And the rust design with unsigned type where subtraction does not return a signed type but may fail at return or silently produce the wrong results, seems the worst possible design imaginable to me. You can ask for whatever you meant, and indeed asking for what you meant is crucial here because if we express ourselves we get the desired results. For example u8::b…
> The truth here is that you might want a lot of different operations and the C choice is not only to provide a single choice, which made a lot more sense 50+ years ago than it does today, but to provide a singularly bad default. C has a single '+' operator, just like Rust has. And what that operator does depends on the types to the left and to the right. You can cast between integer types to achieve different behavi…
Well "regular functions" in the sense that these are methods of the primitive type u8†, and of course neither C nor C++ can do that at all. So, yeah, it's a language thing.
In C++ what you'd do here instead is invent custom types and add the methods you want to the types, and I would give C++ credit here if the stdlib provided say, a bunch-of-bits base type with all the bit-twiddling methods defined and maybe specialisations for the 32-bit and 8-bit unsigned integers or something, but AFAICT it doesn't do anything like that.
"I could go out of my way to do this" is true for everything in any of the general purpose languages by their nature.
† In Rust if we define a function associated to a type T with a "self" first parameter then you can call that function as just a method on any value of type T and the appropriate parameter is inferred. So e.g. u8::checked_sub(u8::MAX, 10) is Some(245) but u8::MAX.checked_sub(10) is also Some(245) because it de-sugars to the same call.
Re: Unsigned sizes: A five year mistake
#147Earlier quoted context omitted.
> The truth here is that you might want a lot of different operations and the C choice is not only to provide a single choice, which made a lot more sense 50+ years ago than it does today, but to provide a singularly bad default. C has a single '+' operator, just like Rust has. And what that operator does depends on the types to the left and to the right. You can cast between integer types to achieve different behavi…
> About u8::unchecked_sub() etc, those are just regular functions. Not really a language thing. Yes, nothing of that is standardized in C Well "regular functions" in the sense that these are methods of the primitive type u8†, and of course neither C nor C++ can do that at all. So, yeah, it's a language thing. In C++ what you'd do here instead is invent custom types and add the methods you want to the types, and I wou…
I really don't care about functions vs methods, what is the difference, it's just syntax. Actually, keeping to regular function calls is mostly more readable to me, compared to using methods, using short unqualified method names, mixing function calls and methods calls, nesting/chaining functions and methods.
Re: Unsigned sizes: A five year mistake
#148Earlier quoted context omitted.
> About u8::unchecked_sub() etc, those are just regular functions. Not really a language thing. Yes, nothing of that is standardized in C Well "regular functions" in the sense that these are methods of the primitive type u8†, and of course neither C nor C++ can do that at all. So, yeah, it's a language thing. In C++ what you'd do here instead is invent custom types and add the methods you want to the types, and I wou…
__builtin_add_overflow() is type-generic as well, what is the big difference to this Rust stuff? I'd say Rust is more ergonomic here (standardized calls, I don't have to resort to GCC builtins). But it's not fundamentally different in capabilities. I really don't care about functions vs methods, what is the difference, it's just syntax. Actually, keeping to regular function calls is mostly more readable to me, compar…
Better ergonomics means it's more likely the programmer writes what they actually meant, and if you do that modern compilers have got better at making what you meant fast even as they remain the same or perhaps slightly worse at converting vague gestures which aren't clear about what you meant into what you had hoped for without expressing it.
Re: Unsigned sizes: A five year mistake
#149Re: Unsigned sizes: A five year mistake
#150Earlier quoted context omitted.
Warnings are just noise, so there's no point in printing them--they will be ignored (maybe not when there is a singular warning, but if warnings are allowed to accumulate beyond some manageable threshold). If a warning is worth printing, it should be treated as an error, and if you treat it as an error, you now are "strict" by definition.
Any reasonably good C code I ever worked with aimed to be warning free. But yes, if you can also make it an error. The flexibility is important though.