【发布时间】:2010-12-16 20:25:05
【问题描述】:
您通常可以对数据类型的最小大小做出任何假设吗?
到目前为止我读过的内容:
- 字符:1 个字节
- 短:2 字节
- int:2 字节,通常为 4 字节
- 长:4 字节
浮动???双???
float.h 和 limits.h 中的值是否依赖于系统?
【问题讨论】:
标签: c types cross-platform
您通常可以对数据类型的最小大小做出任何假设吗?
到目前为止我读过的内容:
浮动???双???
float.h 和 limits.h 中的值是否依赖于系统?
【问题讨论】:
标签: c types cross-platform
short int不得大于int。int不得大于long int。
short int的长度必须至少为 16 位。int的长度必须至少为 16 位。long int的长度必须至少为 32 位。long long int的长度必须至少为 64 位。该标准并不要求这些尺寸中的任何一个都必须不同。这是完全有效的,例如,如果所有四种类型都是 64 位长。
【讨论】:
char 在这个答案中根本没有讨论?
char 定义为至少 8 位(<limits.h> CHAR_BIT 要求至少为 8)。
CHAR_BIT 为 8,这意味着 CHAR_BIT 在普通桌面/工作站/服务器环境中基本上 为 8。唯一的例外是古老的旧式大型机、DSP,可能还有一些嵌入式系统。
是的,float.h 和 limits.h 中的值取决于系统。您永远不应该对类型的宽度做出假设,但标准确实规定了一些最小值。请参阅C99 standard 中的 §6.2.5 和 §5.2.4.2.1。
例如,标准只规定char 应该足够大以容纳执行字符集中的每个字符。它没有说它有多宽。
对于浮点情况,标准提示了类型宽度的给出顺序:
有三种真正的浮点类型,分别指定为float、double和long 双。 32)float 类型的值集是 double 类型的值集的子集; double 类型的值集是 long double 类型的值集的子集。
他们隐含地定义了哪个比另一个更宽,但没有具体定义它们有多宽。 “子集”本身是模糊的,因为 long double 可以具有与 double 完全相同的范围并满足此子句。
这是非常典型的 C 语言方式,每个单独的环境都留下了很多内容。你不能假设,你必须问编译器。
【讨论】:
九年了,仍然没有关于float, double, long double 的最小大小的直接答案。
C 中的类型有任何保证的最小大小吗?
对于 浮点 输入 ...
从实用的角度来看,float 的最小大小是 32 位,double 是 64 位 . C 允许 double 和 long double 共享相似的特征,因此 long double 可以像 double 一样小:Example1 或 80 位或 128 位或 . ..
我可以想象一个兼容 C 的 48 位 double 可能已经存在——但不知道。
现在,让我们想象一下,我们富有的叔叔去世了,给我们留下了一笔财富,用于支付 www.smallest_C_float.com 的发展和文化推广。
C 指定:
float 有限范围至少为 [1E-37…1E+37]。见FLT_MIN, FLT_MAX
(1.0f + FLT_EPSILON) – 1.0f <= 1E-5.
float 支持正负值。
让 X:数字 1-9 让 Y:数字 0-9 让 E:值 -37 到 36 让 S:+ 或 - 设 b: 0 或 1
我们的float 可以最低限度地表示SX.YYYYY*10^E 的所有组合,使用基数为 10。
还需要0.0 和±1E+37(另外3 个)。我们不需要 -0.0、次法线、±无穷大或非数字。
即 2910^5*74 + 3 种组合或 133,200,003,需要至少 27 位进行编码 - 不知何故。回想一下,目标是最小尺寸。
使用经典的 base 2 方法,我们可以假设隐含的 1 并得到 S1.bbbb_bbbb_bbbb_bbbb_b2^e 或 22^17*226 组合或 26 位。
如果我们尝试以 16 为基数,则需要大约 21516^(4 或 5)*57 个组合或至少 26 到 30 位。
结论:一个 C float 至少需要 26 位编码。
A C 的double 不需要比float 表达更大的指数范围,它只是具有不同的最小精度要求。 1E-9.
S1.bbbb_bbbb_bbbb_bbbb_ bbbb_ bbbb_ bbbb_bb2^e --> 22^30*226 组合或 39 位。
在我们的 imagine-if-you-will 计算机上,我们可以有一个 13 位的 char 并因此编码 float, double, long double 而没有填充。这样我们就可以实现一个非填充的26位float和39位double, long double。
1:Microsoft Visual C++ for x86, which makes long double a synonym for double
[编辑] 2020
额外的double 要求可能需要 41 位。可能必须使用 42 位 double 和 28 位 float。将需要审查。大叔会不高兴的。
【讨论】:
但是,新的 C99 指定(在 stdint.h 中)最小尺寸的可选类型,如 uint_least8_t、int_least32_t 等。
(见en_wikipedia_Stdint_h)
【讨论】:
提出此类问题的开发人员通常会处理安排一个打包的struct 以匹配定义的内存布局(如消息协议)。假设语言应直接指定布局 16、24、32 位等字段。
这对于汇编语言和其他与特定 CPU 架构密切相关的应用程序特定语言来说是常规且可接受的,但有时在可能针对谁知道什么样的架构的通用语言中是一个问题。
事实上,C 语言并不是为特定的硬件实现而设计的。它通常被指定,以便 C 编译器实现者可以正确地适应特定 CPU 的实际情况。由 9 位字节、54 位字和 72 位内存地址组成的 Frankenstein 硬件架构可以轻松且明确地映射到 C 功能。 (char 是 9 位;short int、int 和 long int 是 54 位。)
这种普遍性就是为什么 C 规范说“不要对超出 sizeof (char)
目前的现实是——而且未来似乎也如此——软件要求架构提供 8 位字节,并且内存字可作为单个字节寻址。情况并非总是如此。不久前,我在 CDC Cyber 架构上工作,该架构具有 6 位“字节”和 60 位字。一个 C 实现会很有趣。事实上,该架构负责 Pascal 的奇怪打包语义——如果有人记得的话。
【讨论】:
如果您不想检查系统/平台上任何类型的大小(字符的倍数)确实是您期望的大小,您可以这样做:
enum CHECK_FLOAT_IS_4_CHARS
{
IF_THIS_FAILS_FLOAT_IS_NOT_4_CHARS = 1/(sizeof(float) == 4)
};
【讨论】:
static_assert ( sizeof(float)*CHAR_BIT == 32 , "(float) size != 32");
C99 N1256 标准草案
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
C99 指定了两种类型的整数保证:
相对保证
6.2.5 类型:
8 对于任意两个具有相同符号和不同整数转换等级的整数类型 (见 6.3.1.1),整数转换等级较小的类型的取值范围是 其他类型值的子范围。
和6.3.1.1 布尔、字符和整数确定相对转换等级:
1 每个整数类型都有一个整数转换等级,定义如下:
- long long int 的秩应大于 long int 的秩,即 应该大于int的rank,int的rank应该大于short的rank int,应大于signed char的等级。
- 任何无符号整数类型的等级应等于相应的等级 有符号整数类型(如果有)。
- 对于所有整数类型 T1、T2 和 T3,如果 T1 的秩大于 T2 并且 T2 具有 排名大于 T3,则 T1 排名大于 T3
绝对最小尺寸
https://stackoverflow.com/a/1738587/895245 提到过,为了方便,这里引用一下。
5.2.4.2.1 整数类型的大小<limits.h>:
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__ 宏,则保证每种 C 类型的 IEEE 类型,尽管 long double 有几种可能性:Is it safe to assume floating point is represented using IEEE754 floats in C?
【讨论】:
float和double与long double吗?我认为它在链接上已经得到了很好的解释。
float 和 double,
引用标准确实给出了被定义为“正确答案”的内容,但它实际上并不能反映程序的一般编写方式。
人们总是假设 char 是 8 位,short 是 16,int 是 32,long 是 32 或 64,long long 是 64。
这些假设不是一个好主意,但你不会因为做出这些假设而被解雇。
理论上,<stdint.h> 可用于指定固定位宽类型,但您必须为 Microsoft 寻找一个。 (See here for a MS stdint.h.) 这里的问题之一是 C++ 在技术上只需要 C89 兼容性就可以成为一个符合要求的实现;即使对于普通 C,C99 甚至在 2009 年也没有得到完全支持。
说char 没有宽度规范也不准确。有,标准只是避免说它是否签名。以下是 C99 的实际含义:
CHAR_BIT 8SCHAR_MIN -127 // -(27 - 1)SCHAR_MAX +127 // 27 - 1UCHAR_MAX 255 // 28 - 1【讨论】:
9,或16,18,...
int 是 16 位的 - 正如 C 规范所允许的那样。 2016 年每年有 1 亿。
大多数库都这样定义:
#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 而不是标准类型。
【讨论】: