EEVblog Electronics Community Forum
Products => Computers => Programming => Topic started by: snarkysparky on January 19, 2022, 07:57:45 pm
-
I just spent 6 hours finding this one
var &= ~_U_(0x1) << 0 //WRONG!!!!!
var &= ~(_U_(0x1) << 0) // good job !!!
the intent was clearing the bit.
without the parenthesis what was the ~ operator doing ?
-
must be something else going on, << 0 doesn't do anything so it shouldn't matter if it is done after or before ~
-
The ~ without brackets inverts the 1. How that will look like depends on the datatype of the var.
#include "stdio.h"
#include "stdint.h"
void main () {
uint8_t u8Var;
int8_t i8Var;
u8Var = ~0x01;
i8Var = ~0x01;
printf("u8Var = %d\n", u8Var);
printf("i8Var = %d\n", i8Var);
}
Returns
u8Var = 254
i8Var = -2
But in both cases the binary pattern is the same. But langwadt is right, with the << 0 it doesn't matter.
-
Maybe you can tell us...
* What the definition of '_U_()' is
* What the type of 'var' is
* What the compiler you use is
-
#define _U_(x) x ## U /**< C code: Unsigned integer literal constant value */
var is unsigned int on arm compiler so 32 bit
compiler is whatever comes with atmel studio. GCC i think
thanks
-
since <<0 does nothing, there is no difference
https://godbolt.org/z/TTzsrhE74
-
Tried to figure if that could have been some issue due to integer promotion rules, but there doesn't seem to be a problem here.
First idea was that, even if '<< 0' has no effect, it would probably still have triggered the promotion of the left operand. But even so, no reason both variants would be any different in the end.
And to answer your title question, '~' has precedence over '<<' in C.
Since you seem to be using GCC for ARM, nothing exotic there too.
So there must be something else wrong that you have attributed to this.
To make sure, you should look at the generated assembly code (as I did too, and langwadt showed you.)
-
snarkysparky: what makes you think one of the expressions was wrong? Exactly: what was your reasoning, with exact values, exact outcomes and exact expectations.
Also: what’s the purpose of the _U_ macro? Is the issue the same if you write it normally, as 1u?
-
I just spent 6 hours finding this one
var &= ~_U_(0x1) << 0 //WRONG!!!!!
var &= ~(_U_(0x1) << 0) // good job !!!
You are making something up. Considering that the shift is a no-op and everything's explicitly unsigned, there's no difference between the two.
-
#define _U_(x) x ## U /**< C code: Unsigned integer literal constant value */
I hate things like this, yet you can see this in vendor headers/libraries etc. It screams NIH.
U suffix is part of C standard, just use it so everyone knows what you are doing. Using same logic, you could also write
#define _IF_ if
_IF_ (i == 2)
omg();
-
That was the first line of a list of defines. Each shifting further to the right.
#define THE_FIRST (_U_(0x1) << 0)
#define RET_WRD_1 (_U_(0x1) << 1)
#define RET_WRD_2 (_U_(0x1) << 2)
#define RET_WRD_3 (_U_(0x1) << 3)
#define RET_WRD_T1_U (_U_(0x1) << 4)
#define RET_WRD_T2_U (_U_(0x1) << 5)
#define RET_WRD_T3_U (_U_(0x1) << 6)
#define RET_WRD_T1_L (_U_(0x1) << 7)
#define RET_WRD_T2_L (_U_(0x1) << 8)
#define RET_WRD_T3_L (_U_(0x1) << 9)
#define RET_WRD_MAIN_STEP_ERROR (_U_(0x1) << 10)
#define RET_WRD_FEED_STEP_ERROR (_U_(0x1) << 11)
#define RET_WRD_UP_SOLENOID_ERROR (_U_(0x1) << 12)
#define RET_WRD_LW_SOLENOID_ERROR (_U_(0x1) << 13)
#define RET_WRD_CUTTER_MOTOR_ERROR (_U_(0x1) << 14)
#define RET_WRD_CUTTER_FINISHED_OK (_U_(0x1) << 15)
usage was like
if(StatusWord & RET_WRD_UP_SOLENOID_ERROR)DoSomething();
else
DoSomethingElse();
Funny.. It worked with only the first two bit shifts of 0 and 1. When i added the others it failed.
-
Funny.. It worked with only the first two bit shifts of 0 and 1. When i added the others it failed.
Doesn't make sense. If the first two worked, the others would work as well.
Might be a matter of taste, but in my opinion, that coding style to me is more like "preprocessor bragging" ("hey, this is to show I know how the preprocessor's concatenation operator works") than something that would improve code quality or readability. The shifts are o.k. (as it makes immediately obvious which bit is meant), however.
This would do just as well without such unnecessary obfuscation:
#define THE_FIRST (1U << 0)
#define RET_WRD_1 (1U << 1)
#define RET_WRD_2 (1U << 2)
#define RET_WRD_3 (1U << 3)
.
.
.
-
Still does not explain the issue, & has lower priority than <<.
I agree with golden_labels and TheCalligrapher:
What exactly did not work?
At compilation or at run time?
What where the effects (I think we all agree on the expected effect)?
In any case writing a #define like that without surrounding brackets is borderline criminal, as it relies heavily on operator priority rules.
On the pointlessness of the _U_ macro, Siwastaja said it all.
-
what was happening was that when one of the later tests was false and the code to clear the bit executed the whole word was being cleared...
I apologize for not clearly stating what the code was.
there were lines like this for each bit
if(UP_SOL_ERROR) RemIoDiscreteLocalCopy |= RET_WRD_UP_SOLENOID_ERROR;
else
RemIoDiscreteLocalCopy &= ~RET_WRD_UP_SOLENOID_ERROR;
The problem was happening in this part -> RemIoDiscreteLocalCopy &= ~RET_WRD_UP_SOLENOID_ERROR; when #define RET_WRD_LW_SOLENOID_ERROR _U_(0x1) << 13
after changing #define RET_WRD_LW_SOLENOID_ERROR (_U_(0x1) << 13)
it worked.
-
Now it makes sense, and confirm what I wrote:
In any case writing a #define like that without surrounding brackets is borderline criminal, as it relies heavily on operator priority rules.
~ has, as already stated at the beginning of the thread, higher priority than <<.
So the the effect was:
~1u << 13 = 0xFFFFFFFE << 13 = 0xFFFFC000
Bits 0-13 are then lost.
EtA: the define for bit 0 indeed worked as <<0 is not doing anything, the one for bit 1 was clearing bit 0 too.
-
The problem was happening in this part -> RemIoDiscreteLocalCopy &= ~RET_WRD_UP_SOLENOID_ERROR; when #define RET_WRD_LW_SOLENOID_ERROR _U_(0x1) << 13
after changing #define RET_WRD_LW_SOLENOID_ERROR (_U_(0x1) << 13)
it worked.
Well, of course, when the shift is non-zero, it becomes a completely different story. Obviosuly, `~1u << 13` is different from `~(1u << 13)`.
-
The problem was happening in this part -> RemIoDiscreteLocalCopy &= ~RET_WRD_UP_SOLENOID_ERROR; when #define RET_WRD_LW_SOLENOID_ERROR _U_(0x1) << 13
after changing #define RET_WRD_LW_SOLENOID_ERROR (_U_(0x1) << 13)
it worked.
Well, of course, when the shift is non-zero, it becomes a completely different story. Obviosuly, `~1u << 13` is different from `~(1u << 13)`.
Well. Yeah. ;D
Looks like someone has a problem using macros...