Ste*_*mit 16
作为一般规则,C中的大多数算术是使用类型int
(即普通int
,不是short
或long
)来执行的.这是因为(a)C的定义是这样说的,这与(b)许多处理器(至少是C的设计者想到的)更喜欢工作的方式有关.
因此,如果您尝试使用short
ints 来"节省空间" ,那么您可以编写类似的内容
short a = 1, b = 2;
short c = a + b;
Run Code Online (Sandbox Code Playgroud)
编译器发出的代码转换a
,从short
到int
,转换b
来自short
于int
,做加法,并转换总和回short
.您可能已经保存的空间一点点的存储空间a
,b
以及c
,但你的代码很可能要大些(慢).
如果你反而写
int a = 1, b = 2;
int c = a + b;
Run Code Online (Sandbox Code Playgroud)
你花一点点更多的存储空间a
,b
以及c
,但代码可能是更小更快速.
这在某种程度上是一个过于简单的论点,但是你的观察背后是类型的使用short
是罕见的,int
通常建议使用plain .基本上,因为它是机器的"自然"大小,所以它被认为是最简单的算术类型,没有额外的转换和来自不太自然的类型.它有点像"在罗马时,像罗马人那样做"的论点,但它通常会使用普通的int
优势.
如果你有很多不那么大的整数要存储,另一方面(大量的整数,或者包含不那么大整数的大量结构),数据的存储节省可能很大,并且值得与代码大小(相对较小的)增加以及潜在的速度增加进行交易.
另请参阅此前的SO问题和此C FAQ列表条目.
附录:与任何优化问题一样,如果您真的关心数据空间使用,代码空间使用和代码速度,您将需要使用您的确切机器和处理器进行仔细测量.毕竟,您的处理器可能最终不需要任何"额外的转换指令"来转换为较小的类型,因此使用它们可能不会有太大的劣势.但与此同时,您可以确认,对于孤立变量,使用它们可能也不会产生任何可衡量的优势.
附录2.这是一个数据点.我试验了代码
extern short a, b, c;
void f()
{
c = a + b;
}
Run Code Online (Sandbox Code Playgroud)
我编译了两个编译器,gcc和clang(在Mac上编译Intel处理器).后来我改变short
到int
并重新编译.在int
-使用代码为下GCC较小7个字节,并且在铛小10个字节.检查汇编语言输出表明不同之处在于截断结果以便将其存储c
; 取short
而int
不是似乎没有改变指令计数.
然而,我接着尝试调用两个不同的版本,并发现即使在10000000000次调用之后,它在运行时间上几乎没有差别.因此,"使用short
可能使代码更大"的答案部分得到了确认,但也许并非"并且也使其变慢".
这里有几个问题。
首先,该char
类型完全不适合保存整数值。它只能用于保存字符。这是因为它具有实现定义的符号,char
实际上是与signed char
and分开的不同类型unsigned char
。请参阅默认情况下 char 是有符号还是无符号?。
然而,如果可能的话,应该避免使用小整数类型(例如char
和 )的主要原因是隐式类型提升。short
这些类型会受到整数提升的影响,这反过来又可能导致危险的事情,例如符号的无声改变。有关详细信息, 请参阅隐式类型提升规则。
因此,一些编码标准实际上完全禁止使用较小的整数类型。尽管要使这样的规则可行,您需要 32 位或更大的 CPU。因此,如果要考虑各种微控制器,这并不是一个很好的通用解决方案。
另请注意,以这种方式对内存进行微观管理主要与嵌入式系统编程相关。如果您正在编写 PC 程序,使用较小的类型来节省内存可能是一种“过早的优化”。
C 的默认“原始数据类型”,包括char
、short
、 、int
总体来说是相当不可移植的。当代码移植时,它们的大小可能会发生变化,这反过来又会给它们带来不确定的行为。此外,C 允许这些类型使用各种晦涩和奇异的符号格式,例如补码、符号和幅度、填充位等。
坚固、可移植、高质量的代码根本不使用这些类型,而是使用stdint.h
. 作为奖励,该库只允许正常的行业标准二进制补码。
出于上述所有原因,使用较小的整数类型来节省空间并不是一个好主意。再次,stdint.h
是优选的。如果您需要可移植地节省内存的通用类型,除非节省内存意味着降低执行速度,否则请使用int_fast8_t
和 类似的类型。这些将是 8 位,除非使用更大的类型意味着执行速度更快。