6 ms·
For those who aren't C/C++ programmers, the issue here is people using ^ to mean power where it means XOR in C/C++.
by ChrisRR 7y ago
For those who aren't C/C++ programmers, the issue here is people using ^ to mean power where it means XOR in C/C++.
- fefe23 7y agoEven if it meant power, it would make sense to warn here, because storing 2^16 in an unsigned short yields 0 :-)
- cfstras 7y agothese are signed, so you‘re getting -2^16... so many warnings to emit! /edit: had that mixed up in my head. Interestingly, clang does warn about the overflow: main.c:6:17: warning: implicit conversion from 'int' to 'int16_t' (aka 'short') changes value from 65536 to 0 [-Wconstant-conversion] int16_t s16 = 65536;
- enedil 7y agoOops, you meant -2^15 I guess.
- NikkiA 7y agoNo, they meant -2^16, ie, -(0)
- majewsky 7y ago-2^16 is not -0. The unary minus binds more tightly than the binary xor, so this comes out as -2^16 = (-2) ^ 16 = 0b111...1110 ^ 0b10000 = 0b111...11011110 = -18 if I'm not mistaken.
- NikkiA 7y agoNo, we mean the power operator, 2 to the power of 16 would be '0' in a short int, since the value overflows... But since philosophically a signed int has '1's in every bit from the MSB to infinity towards the left, it should thus be -0 not 0.
- leereeves 7y agoIn two's complement (the usual binary representation of signed ints), -0 is the same as 0.
- garmaine 7y agoYeah my own first reaction was “Oh, gcc doesn’t warn about overflow assignment? That’s a definite bug.” I code in C/C++ too, although not exclusively. I facepalmed a few seconds later, but it goes to show the value of having this be a compiler warning.
- quickthrower2 7y agoI am not a C programmer but my opinion with any language is don’t try to catch mistakes like this in the compiler. Instead leave to configurable and competing linters for people who want to catch possible mistakes like this. Anyone caught by this mistake probably hasn’t tested their program adequately. Any mistake induced by the wrong constant number should be easy to weed out with unit testing.
- scatters 7y agoBy the time you write a linter, you've done more than half of the work of a compiler, at which point you might as well just ship it as a compiler. It's a bit different for clang, which is modular and provides libraries that tool writers can use, but gcc is intentionally monolithic.
- gchadwick 7y ago> By the time you write a linter, you've done more than half of the work of a compiler, at which point you might as well just ship it as a compiler. Does depend on what kind of lint you want to catch but something like this 'just' needs some lexing and parsing to give a usable AST that's reasonably clean so it's not too hard to write lint rules against it. (Not trivial for C & C++ hence 'just') Building the full compiler is much more work, especially if you want a decent optimizing compiler.
- barrkel 7y agoThe back end is a lot of work, but so is the front end in a language like C++. In fact most of the essential complexity is in the front end; you make do with a simple back end, but the front end is irreducibly complex if you want it to actually compile the language to spec. And you need the front end to lint, especially if you want to avoid false positives, the bane of linting tools.
- zaarn 7y agoAnd better hope you didn't put in any bugs that GCC does or doesn't have, then you're left helpless as linter and compiler engage in epic battle on who is right.
- dehrmann 7y agoAnd Java, Python, Javascript, Ruby. The list goes on. It's more of a general problem for non-programmers than specifically people who are new to C (unlike the j++ in python someone mentioned).
- phaedrus 7y agoI am a C++ programmer and yet I also failed to catch on that ^ in the ticket was xor not pow until I read the comments. All it took was being a bit sleepy. A rather unfortunate operator choice on the part of C: open to confusion and precluded adding ^ as an exponentiation operator to the language.
- AKrumbach 7y agoWell, that isn't the only bug in the code, just the one which is being requested for prompting the warning. It's been about a decade since I've written significant C/C++ code, but something far more dangerous stood out to me: Upon first reading, I'd assume they are seeing the maximum unsigned values, but their variables aren't declared as unsigned -- and C/C++ default to signed values. Secondly, representing the nth power of two actually takes n+1 binary digits, so e.g. 28 is a one, followed by 8 zeros -- overflowing any 8-bit variable, signed or unsigned! This is undefined behavior as-declared (signed values), but would be entered as a zero for explicitly declared unsigned variables. Personally, if I were to be implementing this, I'd use bitwise operations to generate the correct values, and explicitly acknowledge in a comment something like "the following code knowingly breaks the abstraction of numeric values. It is likely not portable to other hardware, nor should you assume easy extension to other variable types. Das Quellcode ist nicht fur der gefingerpoken!"