AVR-GCC for Linux doesn't handle well 16 bit words

An interesting graph over time that number would make.

It's 2021 and you probably could say 99.99%, and in these fora add some more 9s.

Although… now that we have reliable industrial strength compilers, perhaps the vindictive finger is pointed at them less often - most ppl know to blame the compiler down nearer the end or even off the end of the A, B, C &c. list of things to look at next.


It appear the OP has previous form blaming the compiler for programming errors .

My mistake. I meant: "critical section required if using 16bit variables on a 8bit processor".

Yes, such macros work as expected. Actually, without them the results get crazy (even more!)

What is MWE?

I'll look for my program that doesn't shift left.

My problem is that I'm using a real time kernel that includes its own tick counter, so I can't (yes, I can but I shouldn't) mix counters.

Volatile variables means "do not optimize me!"

When a variable has been declared volatile the compiler does:

  1. Read the variable from the memory and save it into a register.
  2. Process the register as need it.
  3. Save the result into memory.

I did it this way to help me figure the error out. You might want to generate both assembly outputs (volatile and no volatile) to see the difference.


I found my post on stackoverflow: avr gcc - Is there a bug when bit-shifting on the avr-gcc compiler? - Stack Overflow

Every piece of software has bugs. Although the next list seems outdated (maybe the bugs has been fixed since then) one can notice that the compiler is bug-free: AVR Toolchain Bugs

Here you can see the left-shift problem: avr gcc - Is there a bug when bit-shifting on the avr-gcc compiler? - Stack Overflow If that's not a bug, what it is?

It's not a bug in my opinion, it's the way the compiler generates the code; it follows rules. It first does the shift and next it assigns; as the shift is done on the 16-bit variable, you will end up with 0. The way around could have been to first assign the 16-bit variable to the 32-bit variable and next shift the 32-bit variable.


This is not a problem, it's the correct behavior.
It is natural that a (EDIT)unsigned 16-bit variable becomes 0 when it is shifted by 16 bits.


I beg to differ, you describe the behaviour for non-volatile variables. Volatile variables are not kept in registers except for the evaluation of a single expression.

Not as natural as you might think: Arithmetic operators - cppreference.com

if the value of the right operand is negative or is greater or equal to the number of bits in the promoted left operand, the behavior is undefined.

I'm not saying compiler bugs are impossible, but they are extremely unlikely, especially with such a trivial piece of code.

One way to see this - assuming you are confident of the problem - what is a practical course of action? Have you found the line(s) of code that are the definite cause? If you can't fix it, you have to:

  1. Fix it yourself
  2. Convince someone else to fix it.

So, how are you going to accomplish #2? If all the evidence you have is mysteriously buried deeply inside a proprietary program that also uses an RTOS, but you can't actually point to the cause, you are asking someone else (who is not hearing any complaints from anyone else) to dig through all that stuff for you. How many hours do you think that would take? Any renumeration? I didn't think so. So put yourself in their shoes. That is what an MRE does, takes the burden off the maintainer by isolating the problem.

And - this is an Arduino programming forum. Not an AVR-GCC code hub. You can complain here all week and all you would get is sympathy or the lack of it. To get action on something like this, you have to open a pull request or whatever the maintainers use to track bugs.

Also, compiler maintainers don't care about applications. They only try to guarantee that the language specification is adhered to.

Why C is not my preferred language :frowning:

How can somebody define shift behaviour different from the three machine instructions shl, shr and asr, leaving many undefined or implementation specific cases :frowning:

Now at least I see no chance for a compiler bug. Case closed?

Any strongly typed language should barf if you ask it to shift a signed quantity. Just because the processor can do it, doesn't mean it makes any sense.


This would require introducing an alternate "arithmetic shift operator" in C. The lack of it, might be a valid point. But they had to draw the line on features somewhere. C was supposed to be concise.

Not necessarily. Arithmetic shift could be selected with signed types, because it makes sense only there. The user then can switch between shr and asr by casting the operand. But such simple handling might break legacy code, so bad design decisions have to be preserved and detailed further forever :frowning:

I think I understand, you propose that it be selected automatically, according to type. Hey, C/C++ isn't perfect. Someday there will be something much better.

That day was about 30 years ago :wink:

I hope you're not referring to Java...