未知大小的有符号整数类型的最大正值

时间:2017-06-16 21:27:53

标签: c signed-integer

如果我们有一个无符号整数类型,我们可能不知道它的大小,例如size_t,那么我们可以相对简单地得到它可以容纳的最大值:

size_t maximal = -1;

是否有类似的签名整数类型的技术,例如ssize_t?如:

ssize_t smaximal = ???;

注意,可能没有相应的无符号类型,例如time_t (暂时忽略它甚至可能不是整数)

[编辑1] 使用size_t / ssize_t / time_t仅用于说明目的,我正在寻找没有XXX_MAX帮助的一般解决方案。

[编辑2] 这似乎有效,但我不确定这是不是"只是运气":

#include "foo_library_with_no_max_macros_because_they_are_dumb.h"

foo_int_type foo = (((unsigned)-1) >> 1);

(其中foo_int_type的实际类型是通过一些可怕的预处理器goop来确定的,我不想复制)

4 个答案:

答案 0 :(得分:3)

您可以使用<limits.h>中定义的常量:

#include <limits.h>

size_t maximal = SIZE_T_MAX;
ssize_t smaximal = SSIZE_MAX;

答案 1 :(得分:1)

对于签名类型AFAIK,没有简单,完全可移植的方式。 您可以将*_MAX宏放在_Generic宏中,然后您就不必再担心它们了。

#define Z_max(X) \
    _Generic(X,                                                                \
            char: CHAR_MAX,                                                    \
                                                                               \
            signed char: SCHAR_MAX,                                            \
            short: SHRT_MAX,                                                   \
            int: INT_MAX,                                                      \
            long: LONG_MAX,                                                    \
            long long: LLONG_MAX,                                              \
                                                                               \
            unsigned char: UCHAR_MAX,                                          \
            unsigned short : USHRT_MAX,                                        \
            unsigned int: UINT_MAX,                                            \
            unsigned long: ULONG_MAX,                                          \
            unsigned long long: ULLONG_MAX                                     \
        )                                                                      \

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

int main()
{
    printf("%d\n",  Z_max(1)); //prints 2147483647 on my system
}

答案 2 :(得分:1)

如果您不知道类型的大小并且没有库支持来确定最大值,则可以求助于利用二进制表示。

表示有符号整数的常用方法是使用the Two's complement。二进制补码中带符号类型的最大值为零,后跟一个(011111...111)。

现在如何获得这个价值?我们需要从已知值开始并使用按位运算来获得所需的结果。已知值:

  • 0 = 0000...000
  • 1 = 0000...001
  • 等。

没有真正的帮助。但是

  • -1 = 1111...111

让我们相当亲密。现在我们不知道常量FOO_MIN == 1000...000我们可以使用-1 XOR(),因此我们可以求助于位移。如果我们将-1向右移一位并确保将0移入,我们将获得所需的值。

在C中,负值的右移位是实现定义的,因此它可以是算术(在1中移位)和逻辑(在0中移位)移位,并且主要是是算术的(见this answer),所以我们需要在转换之前将值转换为足够大的无符号类型。

这里是:

#include <stdint.h>
#include "foo_library_with_no_max_macros_because_they_are_dumb.h"

foo_int_type foo = ((uint64_t)((foo_int_type)-1)) >> 1;

或者,我们可以使用sizeof()来生成FOO_MIN

#include "foo_library_with_no_max_macros_because_they_are_dumb.h"

foo_int_type foo_min = ((foo_int_type)1) << (8 * sizeof(foo_min) - 1);
foo_int_type foo = ((foo_int_type)-1) ^ foo_min;

答案 3 :(得分:0)

我无法找到表达式,但是使用循环

的函数
#define integer int    /* change as required */
integer max()
{
  integer x=0x7f;
  size_t  n=sizeof(integer)-1;
  while(n--) {
    x <<= 8;           /* may create spurious warning for integer=signed char */
    x |= 0xff;
  }
  return x; 
}

或宏

#define MaxSignedInteger(integer)                    \
  (integer)(sizeof(integer)==1? 0x7f :               \
            sizeof(integer)==2? 0x7fff :             \
            sizeof(integer)==4? 0x7fffffff :         \
                                0x7fffffffffffffffll)