In your code, the type of 1
is (as always) int
. So, if sizeof (int)
is smaller than sizeof (long)
, it stands to reason that you can't shift an int
over all the bits in a long
.
The solution is of course to use an (unsigned) long constant:
data |= 1UL << n;
I made it unsigned since unsigned integers are better suited for bitwise operators. The type of the literal 1UL
is unsigned long
. I find using suffixes nicer than casting, since it's way shorter and part of the literal itself, rather than having a literal of the wrong type and casting it.
Many people seem to expect that in an expression such as:
unsigned long long veryBig = 1 << 35; /* BAD CODE */
the right-hand side should somehow magically adapt to the "needs" of the left-hand side, and thus become of type unsigned long long
(which I just assume has at least 35 bits, this is of course not portable but it's concise). That does not happen, C doesn't work like that. The expression is evaluated, then it's converted (if necessary) to the type on the left for the assignment to work.