I am tasked with finding maximum two's complement integer, or the TMax. I am at a complete loss for how to do this. I know that the correct value is 0x7fffffff, or 2147483647, but I do not know how exactly to get to this result. That's the maximum number for a 32 bit integer. I cannot use functions or conditionals, and at most I can use 4 operations. Can anyone try and help explain this to me? I know the way to find the maximum number for a certain bit count is 2^(bits - 1) - 1, so 2^(31) - 1 = 2147483647
-
Possible duplicate of [How to find TMax without using shifts](https://stackoverflow.com/questions/7300650/how-to-find-tmax-without-using-shifts) – Ganesh Chowdhary Sadanala Oct 17 '18 at 15:53
-
His question allows using a shift. In fact, that's how I answered it. – DrM Oct 17 '18 at 16:26
-
I looked at the question you referenced. I am sorry, it is not the same question. – DrM Oct 17 '18 at 16:32
-
1What not use `INT_MAX` for max `int` or `INTMAX_MAX` for maximum "integer"? – chux - Reinstate Monica Oct 17 '18 at 17:09
-
It may be that the only right answer is 1<<(n-1) -1, the question is to explain that. One of the points is that integer types are not a fixed size in C. So any solution, apart from using the macros, has to accommodate the full range of the integer type that is used. – DrM Oct 17 '18 at 23:40
-
The question that you marked correct, is actually incorrect. I posted a new answer, check it out. This is a standard course work question. – DrM Oct 17 '18 at 23:41
-
Lets clarify something. Do want to TMAX given an integer data type, or TMAX given a number of bits? – DrM Oct 18 '18 at 00:32
4 Answers
Assuming you know that your machine uses two's complement representation, this is how you would do so in a standard compliant manner:
unsigned int x = ~0u;
x >>= 1;
printf("max int = %d\n", (int)x);
By using an unsigned int
, you prevent any implementation defined behavior caused by right shifting a negative value.

- 195,579
- 13
- 168
- 312

- 205,898
- 23
- 218
- 273
-
-
-
@anatolyg you are using the same expression used by him but combinely. – Ganesh Chowdhary Sadanala Oct 17 '18 at 16:25
-
-
This make the very reasonable assumption that `UINT_MAX/2 == INT_MAX`. Although this is very common, C only requires `UINT_MAX >= INT_MAX`. §6.2.5 9. Also. This answer does not need to rely on two's complement at all. – chux - Reinstate Monica Oct 17 '18 at 17:18
-
To the downvoter, OP said he's looking for the "maximum two's complement integer", which implies `int`, whatever the size of `int` may be. OP just assumed 32-bit, as that's what the vast majority of current implementations use. – dbush Oct 17 '18 at 20:43
-
its not correct, try it when int is not 32 bits, it fails. The point is that sizes of integer types are not fixed in C. If this is for a course, any answer other than 1<<(n-1) -1, will be incorrect, What he asked for was an explanation why that is so. – DrM Oct 17 '18 at 23:37
-
@DrM It does work, in fact your answer with the same code **demonstrates** that it works. You're fixating on the OP saying "I know that the correct value is 0x7fffffff", which is **only** correct if `int` is 32 bits. – dbush Oct 17 '18 at 23:39
-
I think it may be that the question is not well defined. If he wants the max for a given type, number of bits unknown, then indeed -1>>1 in the type, will do it. But if he wants the max for a defined number of bits, then the formula is the only way to it without a mask. – DrM Oct 18 '18 at 00:30
find maximum two's complement integer
int TMax = -1u >> 1
or -1u/2
is sufficient when INT_MAX == UINT_MAX/2
to find the maximum int
,
This "works" even if int
is encoded as 2's complement or the now rare 1s complement or sign magnitude.
Better to use
#include <limits.h>
int TMax = INT_MAX;
Other tricks can involve undefined, implementation defined, unspecified behavior which are best avoided in C.

- 143,097
- 13
- 135
- 256
There are two scenarios in which you may be looking for the maximum positive number, either given an integer data type or given a number of bits. The are also two solutions.
Fill and shift right
Working in an integer data type of a size that exactly matches the size of the desired twos complement data type, you might be able to solve the problem by
(unsigned 'type') ^0)>>1
or equivalently,
(unsigned 'type') ^0)/2.
For example, on a machine where short is 16 bits,
(unsigned short) ^0 ==> 0xFFFF (65535)
((unsigned short) ^0 ) >> 1 ==> 0x7FFF (32767)
On a 32 bit data type, this method gives us 0x7FFFFFFF (2147483647).
In C, an integer type has a minimum size only, c.f. an int can be 16 bits, 32 bits, or larger. But, the word size used in the calculation must exactly match that of the intended target.
Also, note that the data must be an unsigned type. The right shift for a signed type is usually implemented as a sign extended shift (the sign bit is copied into the result).
Set the sign bit only and subtract 1
The second technique, which works for any word size equal to or larger than the number of bits of the desired twos complement word size, is
(unsigned integer_type) 1<<(n-1)-1
For example, in any integer word size greater to or larger than 16, we can find the TMAX for 16 as
(unsigned integer_type) 1<<15 ==> binary 1000 0000 0000 0000 (0x8000)
(unsigned integer_type) (1<<15 - 1) == > 0111 1111 1111 1111 (0x7FFF)
This is robust and works on almost any scenario that provides adequate word size.
Again the data type for the calculation has to be unsigned if the word size in the calculation is that of the target. This is not necessary for a larger word size.
Examples
In the first example, we show that the second method works for 32 bits, using long or long long types.
#include <stdio.h>
int main() {
printf( "%ld\n", (long) ( ( ((unsigned long) 1)<<31 ) - 1 ) );
printf( "%lld\n", (long long) ( ( ((unsigned long long) 1)<<31 ) - 1 ) );
}
Output:
2147483647
2147483647
And here we show that the first method, shift right from all bits set, fails when int is not exactly 32 bits, which as noted, is not guaranteed in C.
#include <stdio.h>
int main() {
printf( "from long long %lld (%zu bits)\n", ( (unsigned long long) ~0 )>>1,
sizeof(unsigned long long)*8 );
printf( "from long %ld (%zu bits)\n", ( (unsigned long) ~0 )>>1,
sizeof(unsigned long)*8 );
printf( "from int %d (%zu bits)\n", ( (unsigned int) ~0 )>>1,
sizeof(unsigned int)*8 );
printf( "from short %d (%zu bits)\n", ( (unsigned short) ~0 )>>1,
sizeof(unsigned short)*8 );
}
Output:
from long long 9223372036854775807 (64 bits)
from long 9223372036854775807 (64 bits)
from int 2147483647 (32 bits)
from short 32767 (16 bits)
Again, recall that the C language only guarantees a minimum size for any integer data types. An int can be 16 bits or 32 bits or larger, depending on your platform.

- 2,404
- 15
- 29
-
" the formulate 1<<(n-1)-1 produces the correct answer on any compliant platform" --> No. Certainly on the vast majority of platforms, yet `UINT_MAX == INT_MAX` is possible - even if it only applies to graveyard big-iron. – chux - Reinstate Monica Oct 18 '18 at 01:57
-
Re your 1st comment: Really? How would that work for twos complement? It seems by definition INT_MAX has to be less than UINT_MAX, unless something in hardware steps in to intervene. I've built a lot of hardware, I dont see that happening so readily. – DrM Oct 18 '18 at 02:01
-
-
C has "The range of nonnegative values of a signed integer type is a subrange of the corresponding unsigned integer type" §6.2.5 9 I take "sub-range" to imply an overlapping range. Even with old machines, I've only seen this on the widest types and not `int`. – chux - Reinstate Monica Oct 18 '18 at 02:04
-
Re your 3rd comment, fine. I'll check it and fix it as appropriate. But regardless, that's kinda not the point. – DrM Oct 18 '18 at 02:05
-
[Re](https://stackoverflow.com/questions/52858804/c-find-maximum-twos-complement-integer/52860759#comment92645819_52864874) - Yes you are correct. Code tends to speak louder than surrounding text - useful to comment in the code that it has a short-coming. – chux - Reinstate Monica Oct 18 '18 at 02:06
-
Re your 4th comment, I haven't seen it, and I have been doing this since punch cards and wire wrap programming. – DrM Oct 18 '18 at 02:07
-
I remain with the conjecture that the question is not well phrased. See my last comment on his question. – DrM Oct 18 '18 at 02:08
-
The formula 1<<(n-1) - 1, is actually the text book speaking. Its a question that appears on exams. – DrM Oct 18 '18 at 02:11
-
Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/182058/discussion-between-chux-and-drm). – chux - Reinstate Monica Oct 18 '18 at 02:13
Thanks for the help, everyone! Turns out I cannot use macros, unsigned, or longs. I came to this solution:
~(1 << 31)
That generates the correct output, so I will leave it at that!

- 71
- 2
- 9
-
This code involves integer overflow, which may behave in unexpected ways (undefined behavior). Within the rules of the game (no `unsigned` arithmetic) this is OK, but if not constrained by such rules, better not use this code. – anatolyg Oct 22 '18 at 01:29
-
You really should read my answer again. I revised it to explain how all of this works in a more clear way. What you wrote here is really not the right answer and it will fail on some computers. – DrM Oct 25 '18 at 01:47