Changed behaviour for bit shift operators


#1

We noticed that errors started to appear since I believe a few months in the way the << bit shift operators work.

The problem can be easily replicated with the following code:

hr <- 7;
min <- 22;
server.log(format("time : %d:%d",hr,min))
tim <- hr << 16 + min << 8;
server.log(format("time : %08x", tim))
tim <- (hr << 16) + (min << 8);
server.log(format("time : %08x", tim))
tim <- hr * 65536 + min * 256;
server.log(format("time : %08x", tim))

One would expect this to generate similar results for the three last log statements as the bitshift operator has higher prio then the summation. At least in C it has and it used to be the same in Squirrel as code using the first approach worked fine for years.
Now it doesn’t anymore. We noticed this the first time about 2 months ago but couldn’t nail down the error until I tried this.

When you run it now (in agent or device) it gives the following result :

2018-09-21 10:43:42 +02:00 [Agent] time : 7:22
2018-09-21 10:43:42 +02:00 [Agent] time : 0001c000
2018-09-21 10:43:42 +02:00 [Agent] time : 00071600
2018-09-21 10:43:42 +02:00 [Agent] time : 00071600

it’s clear that the first appraoch gives higher prio to the summation then to the bit shift operator, which should not be the case, I think…

We use these operators extensively to do binary blob bit stuffing. So it’s quite important.

EDIT : checked it in the C-syntax reference and, contrary to my belief, the sommation does have higher precedence. Remains that I am absolutely certain that it did work differently until recently. Did this apparent wrong behaviour got corrected recently ?


#2

I’m fairly sure we haven’t changed this, certainly not recently. In both Squirrel and C, “+” has higher precedence than “<<”, so that “a << b + c << d” means “a << (b+c) << d”:

peter@dosa:~/src/misc$ cat vedecoid.c
#include <stdio.h>

int main()
{
  int hr = 7;
  int min = 22;
  printf("time : %d:%d\n",hr,min);
  int tim = hr << 16 + min << 8;
  printf("time : %08x\n", tim);
  tim = (hr << 16) + (min << 8);
  printf("time : %08x\n", tim);
  return 0;
}
peter@dosa:~/src/misc$ gcc vedecoid.c
peter@dosa:~/src/misc$ ./a.out
time : 7:22
time : 0001c000
time : 00071600
peter@dosa:~/src/misc$ 

#3

I guess it’s actually undefined behaviour in C, as the shift ends up larger than the size of an int. It is possible that Squirrel code which invokes UB in the Squirrel interpreter changed behaviour at some point (but that still wouldn’t have made it match the other precedence). I’ll check later whether bitshifts in Squirrel are clipped to the right size.

Peter


#4

Thanks.
In the meantime we checked our code base and fortunately we’ve used explicit brackets everywhere except in this one case where we’re stuffing a time value in one 4byte integer.