c operator precedence error - Page 1
Forum section: electronics / general

author: snarkysparky
author_rank: Frequent Contributor
timestamp: January 19, 2022, 07:57:45 pm
content: I just spent 6 hours finding this onevar &= ~_U_(0x1) << 0 //WRONG!!!!!var &= ~(_U_(0x1) << 0) // good job !!!the intent was clearing the bit.without the parenthesis what was the ~ operator doing ?

author: langwadt
author_rank: Super Contributor
timestamp: January 19, 2022, 08:28:55 pm
content: must be something else going on, << 0 doesn't do anything so it shouldn't matter if it is done after or before ~

author: Twoflower
author_rank: Frequent Contributor
timestamp: January 19, 2022, 08:29:57 pm
content: The ~ without brackets inverts the 1. How that will look like depends on the datatype of the var.Code: (c)#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);}ReturnsCode:u8Var = 254i8Var = -2But in both cases the binary pattern is the same. But langwadt is right, with the << 0 it doesn't matter.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 19, 2022, 08:40:37 pm
content: Maybe you can tell us...* What the definition of '_U_()' is* What the type of 'var' is* What the compiler you use is

author: snarkysparky
author_rank: Frequent Contributor
timestamp: January 19, 2022, 08:50:24 pm
content: #define _U_(x) x ## U /**< C code: Unsigned integer literal constant value */var is unsigned int on arm compiler so 32 bitcompiler is whatever comes with atmel studio. GCC i thinkthanks

author: langwadt
author_rank: Super Contributor
timestamp: January 19, 2022, 10:11:58 pm
content: since <<0 does nothing, there is no differencehttps://godbolt.org/z/TTzsrhE74

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 19, 2022, 11:16:10 pm
content: 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.)

author: golden_labels
author_rank: Super Contributor
timestamp: January 19, 2022, 11:50:20 pm
content: 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, as1u?

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: January 20, 2022, 04:08:32 am
content: Quote from: snarkysparky on January 19, 2022, 07:57:45 pmYou are making something up. Considering that the shift is a no-op and everything's explicitly unsigned, there's no difference between the two.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 20, 2022, 08:15:05 am
content: Quote from: snarkysparky on January 19, 2022, 08:50:24 pmI 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 writeCode:#define _IF_ if_IF_ (i == 2)omg();

author: snarkysparky
author_rank: Frequent Contributor
timestamp: January 20, 2022, 01:52:01 pm
content: 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) <<#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 likeif(StatusWord & RET_WRD_UP_SOLENOID_ERROR)DoSomething();elseDoSomethingElse();Funny.. It worked with only the first two bit shifts of 0 and 1. When i added the others it failed.

author: mfro
author_rank: Regular Contributor
timestamp: January 20, 2022, 02:38:39 pm
content: Quote from: snarkysparky on January 20, 2022, 01:52:01 pmDoesn'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:Code:#define THE_FIRST (1U << 0)#define RET_WRD_1 (1U << 1)#define RET_WRD_2 (1U << 2)#define RET_WRD_3 (1U << 3)...

author: newbrain
author_rank: Super Contributor
timestamp: January 20, 2022, 02:39:42 pm
content: 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 theexpectedeffect)?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.

author: snarkysparky
author_rank: Frequent Contributor
timestamp: January 20, 2022, 02:47:17 pm
content: 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 bitif(UP_SOL_ERROR) RemIoDiscreteLocalCopy |= RET_WRD_UP_SOLENOID_ERROR;elseRemIoDiscreteLocalCopy &= ~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) << 13after changing #define RET_WRD_LW_SOLENOID_ERROR (_U_(0x1) << 13)it worked.

author: newbrain
author_rank: Super Contributor
timestamp: January 20, 2022, 03:11:47 pm
content: Now it makes sense, and confirm what I wrote:Quote~ has, as already stated at the beginning of the thread, higher priority than <<.So the the effect was:Code:~1u << 13 = 0xFFFFFFFE << 13 = 0xFFFFC000Bits 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.

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: January 21, 2022, 07:42:20 am
content: Quote from: snarkysparky on January 20, 2022, 02:47:17 pmWell, of course, when the shift is non-zero, it becomes a completely different story. Obviosuly, `~1u << 13` is different from `~(1u << 13)`.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 21, 2022, 07:21:58 pm
content: Quote from: TheCalligrapher on January 21, 2022, 07:42:20 amWell. Yeah.Looks like someone has a problem using macros...