2

So I am revising for an exam and I got stuck in this problem:


2.67 ◆◆ You are given the task of writing a procedure int_size_is_32() that yields 1 when run on a machine for which an int is 32 bits, and yields 0 otherwise. You are not allowed to use the sizeof operator. Here is a first attempt:

1 /* The following code does not run properly on some machines */
2 int bad_int_size_is_32() {
3 /* Set most significant bit (msb) of 32-bit machine */
4 int set_msb = 1 << 31;
5 /* Shift past msb of 32-bit word */
6 int beyond_msb = 1 << 32;
7
8 /* set_msb is nonzero when word size >= 32
9 beyond_msb is zero when word size <= 32 */
10 return set_msb && !beyond_msb;
11 }

When compiled and run on a 32-bitSUNSPARC, however, this procedure returns 0. The following compiler message gives us an indication of the problem: warning: left shift count >= width of type

A. In what way does our code fail to comply with the C standard?

B. Modify the code to run properly on any machine for which data type int is at least 32 bits.

C. Modify the code to run properly on any machine for which data type int is at least 16 bits.

__________ MY ANSWERS:

A: When we shift by 31 in line 4, we overflow, bec according to the unsigned integer standard, the maximum unsigned integer we can represent is 2^31-1

B: In line 4 1<<30

C: In line 4 1<<14 and in line 6 1<<16

Am I right? And if not why please? Thank you!

__________ Second tentative answer:

B: In line 4 (1<<31)>>1 and in line 6: int beyond_msb = set_msb+1; I think I might be right this time :)

Johan
  • 74,508
  • 24
  • 191
  • 319
FranXh
  • 4,481
  • 20
  • 59
  • 78
  • probably you can get an alternative from this question http://stackoverflow.com/questions/3319717/is-there-a-bit-equivalent-of-sizeof-in-c – user1717079 Oct 18 '12 at 01:26
  • This is a good question from the book "CS:APP". The content of it in Chapter 2 will serve you well. – halfelf Oct 18 '12 at 02:07
  • This is a compile-time thing. The compiler, the compiler settings, and the machine the compiler was run on will determine the size of an int, not what machine the program is run on. – user2357112 May 16 '14 at 01:11

4 Answers4

4

A: When we shift by 31 in line 4, we overflow, bec according to the unsigned integer standard, the maximum unsigned integer we can represent is 2^31-1

The error is on line 6, not line 4. The compiler message explains exactly why: shifting by a number of bits greater than the size of the type is undefined behavior.

B: In line 4 1<<30

C: In line 4 1<<14 and in line 6 1<<16

Both of those changes will cause the error to not appear, but will also make the function give incorrect results. You will need to understand how the function works (and how it doesn't work) before you fix it.

  • If you say that the error is in line 6 and not in line 4, how would part B cause the error not to appear? And the same applies to part C – FranXh Oct 18 '12 at 01:56
1

For first thing shifting by 30 will not create any overflow as max you can shift is word size w-1. So when w = 32 you can shift till 31.

Overflow occurs when you shift it by 32 bits as lsb will now move to 33rd bit which is out of bound.

So the problem is in line 6 not 4.

For B.

0xffffffff + 1

If it is 32 bit then it will result 0 otherwise some nozero no.

rushikesh.meharwade
  • 174
  • 1
  • 3
  • 11
0

There is absolutely no way to test the size of signed types in C at runtime. This is because overflow is undefined behavior; you cannot tell if overflow has happened. If you use unsigned int, you can just count how many types you can double a value that starts at 1 before the result becomes zero.

If you want to do the test at compile-time instead of runtime, this will work:

struct { int x:N; };

where N is replaced by successively larger values. The compiler is required to accept the program as long as N is no larger than the width of int, and reject it with a diagnostic/error when N is larger.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
0

You should be able to comply with the C standard by breaking up the shifts left.

B -

Replace Line 6 with

int beyond_msb = (1 << 31) << 1;

C -

Replace Line 4 with

int set_msb = ((1 << 15) << 15) << 1 ;

Replace Line 6 with

int beyond_msb = ((1 << 15) << 15) << 2;

Also, as an extension to the question the following should satisify both B and C, and keep runtime error safe. Shifting left a bit at a time until it reverts back to all zeroes.

int int_size_is_32() {
//initialise our test integer variable.
int x = 1;  
//count for checking purposes
int count = 0;
//keep shifting left 1 bit until we have got pushed the 1-bit off the left of the value type space.
while ( x != 0 ) {
    x << 1   //shift left
    count++;  
}

return (count==31);
}
frogmanx
  • 2,620
  • 1
  • 18
  • 20