C 中的类型有保证最小尺寸吗?

发布于 2024-08-11 09:12:51 字数 221 浏览 7 评论 0原文

您通常可以对数据类型的最小大小做出任何假设吗?

到目前为止我读过的内容:

  • char:1字节
  • 短:2字节
  • int:2字节,通常4字节
  • 长:4字节

浮点???双倍的???

float.hlimits.h 中的值是否依赖于系统?

Can you generally make any assumptions about the minimum size of a data type?

What I have read so far:

  • char: 1 Byte
  • short: 2 Byte
  • int: 2 Byte, typically 4 Byte
  • long: 4 Byte

float??? double???

Are the values in float.h and limits.h system dependent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

江湖彼岸 2024-08-18 09:12:51

维基百科文章对此进行了介绍:

short int 不得大于 int
int 不得大于 long int

short int 的长度必须至少为 16 位。
int 的长度必须至少为 16 位。
long int 的长度必须至少为 32 位。
long long int 的长度必须至少为 64 位。

该标准并不要求这些尺寸必须有所不同。例如,如果所有四种类型都是 64 位长,则它是完全有效的。

This is covered in the Wikipedia article:

A short int must not be larger than an int.
An int must not be larger than a long int.

A short int must be at least 16 bits long.
An int must be at least 16 bits long.
A long int must be at least 32 bits long.
A long long int must be at least 64 bits long.

The standard does not require that any of these sizes be necessarily different. It is perfectly valid, for example, if all four types are 64 bits long.

转瞬即逝 2024-08-18 09:12:51

是的,float.hlimits.h 中的值与系统相关。您永远不应该对类型的宽度做出假设,但标准确实规定了一些最小值。请参阅 C99 中的第 6.2.5 节和第 5.2.4.2.1 节标准

例如,标准仅规定 char 应足够大以容纳执行字符集中的每个字符。它没有说它有多宽。

对于浮点情况,标准提示给出类型宽度的顺序:

§6.2.5.10

存在三种真正的浮动类型,指定为floatdoublelong
双。 32) float 类型的值集是 double 类型的值集的子集; double 类型的值集是 long double 类型的值集的子集。


他们隐含地定义了哪个比另一个更宽,但没有具体定义它们有多宽。 “子集”本身是模糊的,因为 long double 可以具有与 double 完全相同的范围并满足此子句。

这是 C 语言的典型运行方式,每个单独的环境都有很多工作要做。你不能假设,你必须问编译器。

Yes, the values in float.h and limits.h are system dependent. You should never make assumptions about the width of a type, but the standard does lay down some minimums. See §6.2.5 and §5.2.4.2.1 in the C99 standard.

For example, the standard only says that a char should be large enough to hold every character in the execution character set. It doesn't say how wide it is.

For the floating-point case, the standard hints at the order in which the widths of the types are given:

§6.2.5.10

There are three real floating types, designated as float, double, and long
double
. 32) The set of values of the type float is a subset of the set of values of the type double; the set of values of the type double is a subset of the set of values of the type long double.

They implicitly defined which is wider than the other, but not specifically how wide they are. "Subset" itself is vague, because a long double can have the exact same range of a double and satisfy this clause.

This is pretty typical of how C goes, and a lot is left to each individual environment. You can't assume, you have to ask the compiler.

走过海棠暮 2024-08-18 09:12:51

九年了,仍然没有关于 float、double、long double最小大小的直接答案。


C 中的类型有保证的最小大小吗?

对于浮点类型...

实用的角度来看,float最小大小为32位double64 位。 C 允许 doublelong double 具有相似的特征,因此 long double 可以和 double 一样小:示例1或80位或128位或者...

我可以想象一个符合 C 标准的 48 位 double 可能已经存在 - 但不知道有什么。


现在,让我们想象一下,我们富有的叔叔去世了,给我们留下了一笔财富,用于支付www.smallest_C_float.com的开发和文化推广。

C 指定:

  1. float 有限范围至少为 [1E-37…1E+37]。请参阅FLT_MIN、FLT_MAX

  2. (1.0f + FLT_EPSILON) – 1.0f <= 1E-5

  3. float 支持正值和负值。

    设 X:数字 1-9
    设 Y:数字 0-9
    令E:值-37到36
    设 S:+ 或 -
    设b:0或1

我们的 float 可以使用以 10 为基数的 SX.YYYYY*10^E 最低限度地表示所有组合。

还需要 0.0±1E+37(另外 3 个)。我们不需要 -0.0、次正常值、±无穷大或非数字。

即 2*9*105*74 + 3 个组合或 133,200,003,至少需要 27 位进行编码 - 不知何故。回想一下,目标是最小尺寸。

使用经典的基数为 2 的方法,我们可以假设隐含的 1 并得到
S1.bbbb_bbbb_bbbb_bbbb_b*2e 或 2*217*226 组合或 26 位。

如果我们尝试以 16 为基数,则需要大约 2*15*16(4 或 5)*57 个组合或至少 26 到 30 位。

结论:AC float 至少需要 26 位编码。


C 的double 不需要表达比float 更大的指数范围,它仅具有不同的最小精度要求。 1E-9

S1.bbbb_bbbb_bbbb_bbbb_ bbbb_ bbbb_ bbbb_bb*2e --> 2*230*226 组合或 39 位。


在我们的想象一下计算机上,我们可以有一个 13 位 char,因此可以对 float、double、long double 进行编码,而无需填充。这样我们就可以实现一个非填充的26位float和39位double, long double


1Microsoft Visual C++ for x86,它使 long double double 的同义词


[编辑] 2020

额外的 double 要求可能需要 41 位。可能必须使用 42 位 double 和 28 位 float。需要复查。叔叔会不高兴的。

Nine years and still no direct answer about the minimum size for float, double, long double.


Any guaranteed minimum sizes for types in C?

For floating point type ...

From a practical point-of-view, float minimum size is 32-bits and double is 64- bits. C allows double and long double to share similar characteristics, so a long double could be as small as a double: Example1 or 80-bit or 128-bit or ...

I could imagine a C compliant 48-bit double may have existed – yet do not know of any.


Now, let us imagine our rich uncle dies and left us a fortune to pay for the development and cultural promotion for www.smallest_C_float.com.

C specifies:

  1. float finite range is at least [1E-37… 1E+37]. See FLT_MIN, FLT_MAX

  2. (1.0f + FLT_EPSILON) – 1.0f <= 1E-5.

  3. float supports positive and negative values.

    Let X: Digit 1-9
    Let Y: Digit 0-9
    Let E: value -37 to 36
    Let S: + or -
    Let b: 0 or 1

Our float could minimally represent all the combinations, using base 10, of SX.YYYYY*10^E.

0.0 and ±1E+37 are also needed (3 more). We do not need -0.0, sub-normals, ±infinity nor not-a-numbers.

That is 2*9*105*74 + 3 combinations or 133,200,003 which needs at least 27 bits to encode - somehow. Recall the goal is minimal size.

With a classic base 2 approach, we can assume an implied 1 and get
S1.bbbb_bbbb_bbbb_bbbb_b*2e or 2*217*226 combinations or 26 bits.

If we try base 16, we then need about 2*15*16(4 or 5)*57 combinations or at least 26 to 30 bits.

Conclusion: A C float needs at least 26 bits of encoding.


A C’s double need not express a greater exponential range than float, it only has a different minimal precision requirement. 1E-9.

S1.bbbb_bbbb_bbbb_bbbb_ bbbb_ bbbb_ bbbb_bb*2e --> 2*230*226 combinations or 39 bits.


On our imagine-if-you-will computer, we could have a 13-bit char and so encode float, double, long double without padding. Thus we can realize a non-padded 26-bit float and 39-bit double, long double.


1: Microsoft Visual C++ for x86, which makes long double a synonym for double


[Edit] 2020

Additional double requirements may require 41 bits. May have to use 42-bit double and 28-bit float. Will need to review. Uncle will not be happy.

她比我温柔 2024-08-18 09:12:51

但是,新的 C99 指定(在 stdint.h 中)最小大小的可选类型,例如 uint_least8_t、int_least32_t 等。< br>
(参见en_wikipedia_Stdint_h

However, the new C99 specifies (in stdint.h) optional types of minimal sizes, like uint_least8_t, int_least32_t, and so on..
(see en_wikipedia_Stdint_h)

故人爱我别走 2024-08-18 09:12:51

如果您不想检查系统/平台上任何类型的大小(以字符的倍数为单位)是否确实是您期望的大小,您可以这样做:

enum CHECK_FLOAT_IS_4_CHARS
{
   IF_THIS_FAILS_FLOAT_IS_NOT_4_CHARS = 1/(sizeof(float) == 4)
};

If you wan't to check the size (in multiples of chars) of any type on your system/platform really is the size you expect, you could do:

enum CHECK_FLOAT_IS_4_CHARS
{
   IF_THIS_FAILS_FLOAT_IS_NOT_4_CHARS = 1/(sizeof(float) == 4)
};
乙白 2024-08-18 09:12:51

通常,提出此类问题的开发人员正在处理排列打包结构以匹配定义的内存布局(对于消息协议)。假设该语言应直接指定布局 16 位、24 位、32 位等字段。

对于汇编语言和与特定 CPU 体系结构紧密相关的其他特定于应用程序的语言来说,这是常规的且可以接受的,但对于可能针对谁知道哪种体系结构的通用语言来说,有时会出现问题。

事实上,C 语言并不是为特定的硬件实现而设计的。它是一般性指定的,以便 C 编译器实现者可以正确地适应特定 CPU 的实际情况。由 9 位字节、54 位字和 72 位内存地址组成的弗兰肯斯坦硬件架构可以轻松且明确地映射到 C 功能。 (char 为 9 位;short intintlong int 为 54 位。)

这种通用性是为什么 C 规范说了这样的话:“不要对超出 sizeof (char) <= sizeof (short int) <= sizeof (int) <= sizeof (long int) 的 int 大小抱有太多期望。 ”这意味着字符可以与长整型具有相同的大小!

当前的现实是——而且未来似乎也是如此——软件要求架构提供 8 位字节,并且内存字可作为单独的字节进行寻址。情况并非总是如此。不久前,我研究了 CDC Cyber​​ 架构,该架构具有 6 位“字节”和 60 位字。 AC 对此的实施将会很有趣。事实上,该架构负责 Pascal 奇怪的打包语义——如果有人还记得的话。

Often developers asking this kind of question are dealing with arranging a packed struct to match a defined memory layout (as for a message protocol). The assumption is that the language should directly specify laying out 16-, 24-, 32-bit, etc. fields for the purpose.

That is routine and acceptable for assembly languages and other application-specific languages closely tied to a particular CPU architecture, but is sometimes a problem in a general purpose language which might be targeted at who-knows-what kind of architecture.

In fact, the C language was not intended for a particular hardware implementation. It was specified generally so a C compiler implementer could properly adapt to the realities of a particular CPU. A Frankenstein hardware architecture consisting of 9 bit bytes, 54 bit words, and 72 bit memory addresses is easily—and unambiguously—mapped to C features. (char is 9 bits; short int, int, and long int are 54 bits.)

This generality is why the C specification says something to the effect of "don't expect much about the sizes of ints beyond sizeof (char) <= sizeof (short int) <= sizeof (int) <= sizeof (long int)." That implies that chars could be the same size as longs!

The current reality is—and the future seems to hold—that software demands architectures provide 8-bit bytes and that memory words addressable as individual bytes. This wasn't always so. Not too long ago, I worked on an the CDC Cyber architecture which features 6 bit "bytes" and 60 bit words. A C implementation on that would be interesting. In fact, that architecture is responsible for the weird packing semantics of Pascal—if anyone remembers that.

萤火眠眠 2024-08-18 09:12:51

C99 N1256标准草案

http ://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

C99 指定了两种类型的整数保证:

  • 最小大小保证
  • 类型之间的相对大小

相对保证< /strong>

6.2.5 类型

8 对于任何两个具有相同符号和不同整数转换等级的整数类型
(见6.3.1.1),整数转换等级较小的类型的取值范围是a
其他类型值的子范围。

6.3.1.1 布尔值、字符和整数确定相对转换等级:

1 每个整数类型都有一个整数转换等级,定义如下:

  • long long int 的等级应大于 long int 的等级,即
    应大于 int 的等级,而 int 的等级应大于 Short 的等级
    int,应大于有符号字符的排名。
  • 任何无符号整数类型的等级应等于相应的等级
    有符号整数类型(如果有)。
  • 对于所有整数类型 T1、T2 和 T3,如果 T1 的秩大于 T2 并且 T2 的秩高
    等级高于 T3,则 T1 的等级高于 T3

绝对最小尺寸

https://stackoverflow 提及。 com/a/1738587/895245 ,为了方便起见,这里引用一下。

5.2.4.2.1 整数类型的大小

1 [...]它们的实现定义值的大小(绝对值)应等于或大于所示的值[...]

  • UCHAR_MAX 255 // 2 8 - 1
  • USHRT_MAX 65535 // 2 16 - 1
  • UINT_MAX 65535 // 2 16 - 1
  • ULONG_MAX 4294967295 // 2 32 − 1
  • ULLONG_MAX 18446744073709551615 // 2 64 − 1

浮点

如果定义了 __STDC_IEC_559__ 宏,则保证每个浮点数的 IEEE 类型C 类型,尽管 long double 有一些可能性:假设浮点数在 C 中使用 IEEE754 浮点数表示是否安全?

C99 N1256 standard draft

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

C99 specifies two types of integer guarantees:

  • minimum size guarantees
  • relative sizes between the types

Relative guarantees

6.2.5 Types:

8 For any two integer types with the same signedness and different integer conversion rank
(see 6.3.1.1), the range of values of the type with smaller integer conversion rank is a
subrange of the values of the other type.

and 6.3.1.1 Boolean, characters, and integers determines the relative conversion ranks:

1 Every integer type has an integer conversion rank defined as follows:

  • The rank of long long int shall be greater than the rank of long int, which
    shall be greater than the rank of int, which shall be greater than the rank of short
    int, which shall be greater than the rank of signed char.
  • The rank of any unsigned integer type shall equal the rank of the corresponding
    signed integer type, if any.
  • For all integer types T1, T2, and T3, if T1 has greater rank than T2 and T2 has
    greater rank than T3, then T1 has greater rank than T3

Absolute minimum sizes

Mentioned by https://stackoverflow.com/a/1738587/895245 , here is the quote for convenience.

5.2.4.2.1 Sizes of integer types <limits.h>:

1 [...] Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown [...]

  • UCHAR_MAX 255 // 2 8 − 1
  • USHRT_MAX 65535 // 2 16 − 1
  • UINT_MAX 65535 // 2 16 − 1
  • ULONG_MAX 4294967295 // 2 32 − 1
  • ULLONG_MAX 18446744073709551615 // 2 64 − 1

Floating point

If the __STDC_IEC_559__ macro is defined, then IEEE types are guaranteed for each C type, although long double has a few possibilities: Is it safe to assume floating point is represented using IEEE754 floats in C?

诺曦 2024-08-18 09:12:51

引用该标准确实给出了定义为“正确答案”的内容,但它实际上并没有反映程序通常编写的方式。

人们总是假设 char 是 8 位、short 是 16 位、int 是 32 位、long 是 32 或 64 位、long long 是 64 位。

这些假设不是一个好主意,但你不会因为做出这些假设而被解雇。

理论上, 可用于指定固定位宽度类型,但您必须向 Microsoft 寻找一个。 (请参阅此处获取 MS stdint.h。)此处的问题之一从技术上来说,C++ 只需要兼容 C89 即可成为一致的实现;即使对于普通 C,即使在 2009 年,C99 也没有得到完全支持。

char 没有宽度规范也是不准确的。有,标准只是避免说是否有签名。 C99 实际上是这么说的:

  • 非位域(字节)的最小对象的位数
    CHAR_BIT 8
  • 有符号字符类型的对象的最小值
    SCHAR_MIN -127 // -(27 - 1)
  • signed char 类型对象的最大值
    SCHAR_MAX +127 // 27 - 1
  • unsigned char 类型对象的最大值
    UCHAR_MAX 255 // 28 - 1

Quoting the standard does give what is defined to be "the correct answer" but it doesn't actually reflect the way programs are generally written.

People make assumptions all the time that char is 8 bits, short is 16, int is 32, long is either 32 or 64, and long long is 64.

Those assumptions are not a great idea but you will not get fired for making them.

In theory, <stdint.h> can be used to specify fixed-bit-width types, but you have to scrounge one up for Microsoft. (See here for a MS stdint.h.) One of the problems here is that C++ technically only needs C89 compatibility to be a conforming implementation; even for plain C, C99 is not fully supported even in 2009.

It's also not accurate to say there is no width specification for char. There is, the standard just avoids saying whether it is signed or not. Here is what C99 actually says:

  • number of bits for smallest object that is not a bit-field (byte)
    CHAR_BIT 8
  • minimum value for an object of type signed char
    SCHAR_MIN -127 // -(27 - 1)
  • maximum value for an object of type signed char
    SCHAR_MAX +127 // 27 - 1
  • maximum value for an object of type unsigned char
    UCHAR_MAX 255 // 28 - 1
丢了幸福的猪 2024-08-18 09:12:51

大多数库都定义了这样的内容:

#ifdef MY_ARCHITECTURE_1
typedef unsigned char u_int8_t;
typedef short int16_t;
typedef unsigned short u_int16_t;
typedef int int32_t;
typedef unsigned int u_int32_t;
typedef unsigned char u_char;
typedef unsigned int u_int;
typedef unsigned long u_long;
typedef unsigned short u_short;
#endif

然后您可以在程序中使用这些 typedef 而不是标准类型。

Most of the libraries define something like this:

#ifdef MY_ARCHITECTURE_1
typedef unsigned char u_int8_t;
typedef short int16_t;
typedef unsigned short u_int16_t;
typedef int int32_t;
typedef unsigned int u_int32_t;
typedef unsigned char u_char;
typedef unsigned int u_int;
typedef unsigned long u_long;
typedef unsigned short u_short;
#endif

you can then use those typedef in your programs instead of the standard types.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文