0

Given:

#include <stdio.h>
#include <limits.h>

int main()
{
  if (sizeof (long) > sizeof (int)) {
    long x = 42;
    x <<= CHAR_BIT * sizeof (int);
  }

  printf("sizeof (long) == %d\n", (int) sizeof (long));
  printf("sizeof (int) == %d\n", (int) sizeof (int));

  return 0;
}

On a platform where the sizes are equal I get this, with various version of GCC:

$ gcc -Wall shiftcomplain.c  -o shiftcomplain
shiftcomplain.c: In function ‘main’:
shiftcomplain.c:8:5: warning: left shift count >= width of type [enabled by default]
$ ./shiftcomplain 
sizeof (long) == 4
sizeof (int) == 4

The code block is not reachable when the types have an equal size, so the bad shift will never execute. It will only execute if long is wider than int, in which case the shift will not be out of range for that type.

How can we eliminate this annoying warning, with these constraints:

  • I don't want to disable it globally because it is useful (when not falsely positive).

  • I don't want split the shift---that is, perform it as two consecutive left shifts which add to the desired shift size.

  • I don't want to convert the if test into a preprocessor #if. (This is easy to do in this case with INT_MAX and LONG_MAX, but troublesome in the actual program.)


Based on n.m.'s answer, I'm using something very similar to the following pattern:

const int condition = sizeof (long) > sizeof (int);

if (condition) {
  /*...*/
  x <<= CHAR_BIT * sizeof (int) * condition;
}

This pattern applied in my actual code suppresses the diagnostic, and the generated code doesn't change compared to not multiplying by condition.

Kaz
  • 55,781
  • 9
  • 100
  • 149

2 Answers2

2
x <<= (sizeof (long) > sizeof (int) ? CHAR_BIT * sizeof (int) : 0);
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
0

I was on the same path as n.m. but came up with the following which seems more semantically what might have been intended (the top sizeof(int) bytes are from x).

x <<= (sizeof(long) - sizeof(int))*CHAR_BIT;
Anders
  • 2,270
  • 11
  • 19
  • 1
    You are assuming `sizeof(long) - sizeof(int) == sizeof(int)` which is not necessarily true. – P.P Dec 05 '15 at 18:00
  • True, I noticed that. The question is whether the intent is to left-justify the field or what? n.m. did the exact transcription. – Anders Dec 05 '15 at 19:55
  • On some weird platform with 6 byte longs and 4 byte ints, do you want it to shift by 2 bytes or shift by four and get the warning and cut off the field? – Anders Dec 05 '15 at 19:57
  • BTW, both of these answers are somewhat unsatisfying. I also wish GCC had a localized way to silence warnings for "false positives" or "intentional" constructs once they have been checked. Oooh, I just found: http://stackoverflow.com/a/3125889/5226168 and http://stackoverflow.com/a/3394268/5226168. YAY!!! – Anders Dec 05 '15 at 20:01
  • @BlueMoon - oh, that was just rhetorical :) Maybe I should have said "did the author". – Anders Dec 05 '15 at 20:05