Author Topic: c operator precedence error  (Read 1686 times)

0 Members and 1 Guest are viewing this topic.

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 353
  • Country: us
c operator precedence error
« 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 ?



 

Online langwadt

  • Super Contributor
  • ***
  • Posts: 3088
  • Country: dk
Re: c operator precedence error
« Reply #1 on: January 19, 2022, 08:28:55 pm »
must be something else going on, << 0 doesn't do anything so it shouldn't matter if it is done after or before ~
 

Offline Twoflower

  • Frequent Contributor
  • **
  • Posts: 704
  • Country: de
Re: c operator precedence error
« Reply #2 on: January 19, 2022, 08:29:57 pm »
The ~ without brackets inverts the 1. How that will look like depends on the datatype of the var.

Code: (c) [Select]
#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
Code: [Select]
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.

« Last Edit: January 19, 2022, 08:32:08 pm by Twoflower »
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9543
  • Country: fr
Re: c operator precedence error
« Reply #3 on: January 19, 2022, 08:40:37 pm »
Maybe you can tell us...

* What the definition of '_U_()' is
* What the type of 'var' is
* What the compiler you use is
 

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 353
  • Country: us
Re: c operator precedence error
« Reply #4 on: January 19, 2022, 08:50:24 pm »
#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
 

Online langwadt

  • Super Contributor
  • ***
  • Posts: 3088
  • Country: dk
Re: c operator precedence error
« Reply #5 on: January 19, 2022, 10:11:58 pm »
since <<0 does nothing, there is no difference

https://godbolt.org/z/TTzsrhE74
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9543
  • Country: fr
Re: c operator precedence error
« Reply #6 on: January 19, 2022, 11:16:10 pm »
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.)
 

Offline golden_labels

  • Frequent Contributor
  • **
  • Posts: 630
  • Country: pl
Re: c operator precedence error
« Reply #7 on: January 19, 2022, 11:50:20 pm »
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?


« Last Edit: January 19, 2022, 11:59:38 pm by golden_labels »
Dihydrogen monoxide was responsible for Fukushima, Chernobyl and TMI disasters
Worth watching: Calling Bullshit — protect your friends and yourself from bullshit!
 
The following users thanked this post: MK14

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 102
  • Country: us
Re: c operator precedence error
« Reply #8 on: January 20, 2022, 04:08:32 am »
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.
« Last Edit: January 20, 2022, 04:10:49 am by TheCalligrapher »
 
The following users thanked this post: MK14

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 5611
  • Country: fi
Re: c operator precedence error
« Reply #9 on: January 20, 2022, 08:15:05 am »
#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
Code: [Select]
#define _IF_  if

_IF_ (i == 2)
   omg();
 
The following users thanked this post: Ian.M, newbrain, MK14

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 353
  • Country: us
Re: c operator precedence error
« Reply #10 on: January 20, 2022, 01:52:01 pm »
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.
 

Offline mfro

  • Regular Contributor
  • *
  • Posts: 152
  • Country: de
Re: c operator precedence error
« Reply #11 on: January 20, 2022, 02:38:39 pm »
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:
Code: [Select]
#define THE_FIRST                                 (1U << 0)
#define RET_WRD_1                                 (1U << 1)
#define RET_WRD_2                                 (1U << 2)
#define RET_WRD_3                                 (1U << 3)
.
.
.
Beethoven wrote his first symphony in C.
Nach oben
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1389
  • Country: se
Re: c operator precedence error
« Reply #12 on: January 20, 2022, 02:39:42 pm »
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.
Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: Ian.M, MK14

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 353
  • Country: us
Re: c operator precedence error
« Reply #13 on: January 20, 2022, 02:47:17 pm »
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.




 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1389
  • Country: se
Re: c operator precedence error
« Reply #14 on: January 20, 2022, 03:11:47 pm »
Now it makes sense, and confirm what I wrote:
Quote
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:
Code: [Select]
~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.
« Last Edit: January 20, 2022, 03:24:47 pm by newbrain »
Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: Ian.M, MK14, snarkysparky

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 102
  • Country: us
Re: c operator precedence error
« Reply #15 on: January 21, 2022, 07:42:20 am »
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)`.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 9543
  • Country: fr
Re: c operator precedence error
« Reply #16 on: January 21, 2022, 07:21:58 pm »
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...
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf