sizeof
是C语言的一个关键字,它返回一个名为size_t
的类型的大小。然而,size_t
并不是一个关键字,而是主要在stddef.h
以及可能其他的C标准头文件中定义的。
考虑这样一种情况:您想创建一个不包括任何C标准头文件或库的C程序(比如创建操作系统内核)。在这种代码中,可以使用sizeof
(它是C语言的一个关键字,因此是该“语言”的一部分),但是它所返回的类型(size_t
)是不可用的!
这难道不意味着C标准规范存在某种问题吗?能否澄清一下这个问题?
sizeof
是C语言的一个关键字,它返回一个名为size_t
的类型的大小。然而,size_t
并不是一个关键字,而是主要在stddef.h
以及可能其他的C标准头文件中定义的。
考虑这样一种情况:您想创建一个不包括任何C标准头文件或库的C程序(比如创建操作系统内核)。在这种代码中,可以使用sizeof
(它是C语言的一个关键字,因此是该“语言”的一部分),但是它所返回的类型(size_t
)是不可用的!
这难道不意味着C标准规范存在某种问题吗?能否澄清一下这个问题?
它并不会直接返回类型为 size_t 的值,因为 size_t 本身不是一个具体的类型,而是一个未指定的内置类型的 typedef 别名。typedef 标识符(例如 size_t)与其相应的基础类型完全等效(并在编译时转换为其基础类型)。如果在您的平台上将 size_t 定义为 unsigned int,则在系统上编译时,sizeof 返回一个 unsigned int。size_t 只是一种方便的方式来保持可移植性,如果您只是通过名称显式使用它,则只需要在 stddef.h 中包含它。
sizeof
是一个关键字,尽管它的名称和用法,但它像 +
、=
或 <
一样是一个 运算符,而不是像 printf()
、atoi()
或 fgets()
一样是一个 函数。很多人忘记了(或者根本不知道)sizeof
实际上是一个运算符,并且始终在编译时解析,而不是在运行时解析。
C 语言并不需要 size_t
才能成为一个可用的、一致的语言。这只是标准库的一部分。C 语言需要所有的运算符。如果 C 使用关键字 plus
来加法操作,那么你就可以将其作为运算符。
此外,我经常将 size_t
隐式转换为 unsigned int
(以及常规的 int
,但 Kernighan 和 Ritchie 迟早会因此惩罚我)。如果您愿意,可以将 sizeof
的返回类型分配给 int,但在我的工作中,我通常直接将其传递给 malloc()
或其他类似函数。
C标准中定义了一些适用于自由环境的头文件,例如在操作系统内核中使用。它们不定义任何函数,仅定义和typedef。
它们是float.h、iso646.h、limits.h、stdarg.h、stdbool.h、stddef.h和stdint.h。
在操作系统上工作时,从这些头文件开始并不是一个坏主意。有了它们,你的内核许多事情就会变得更容易。特别是stdint.h将变得非常方便(uint32_t等)。
<float.h>
<iso646.h>
<limits.h>
<stdarg.h>
<stdbool.h>
<stddef.h>
<stdint.h>
<stddef.h>
中的offsetof
宏以及<stdarg.h>
中的可变参数列表宏和类型),但是它们可以处理而无需将其构建为完整关键字。我认为 size_t
不是关键字的主要原因有:
例如,在讨论 C++ 标准的下一个主要修订时,Stroustrup 说到:
C++0x 的改进应该以使得结果语言更易学习和使用的方式完成。 委员会的经验法则之一是:
...
- 优先使用标准库设施而不是语言扩展
...
sizeof
返回一个库类型 size_t
的表达式,这感觉相当奇怪。 :) - musiphilsize_t
为sizeof
运算符产生的类型。 - Michael Burr即使您正在开发内核,也没有理由不包含stddef.h - 它为特定编译器定义了类型大小,任何代码都需要。
还要注意的是,几乎所有的C编译器都是自编译的。因此,sizeof运算符的实际编译器代码将使用size_t并引用与用户代码相同的stddef.h文件。
size_t实际上是一种类型,通常是无符号整数。Sizeof是一个运算符,用于获取类型的大小。sizeof返回的类型实际上是与实现相关的,而不是C标准。它只是一个整数。
编辑: 非常清楚的是,您不需要size_t类型才能使用sizeof。我认为您要找的答案是 - 是的,它不一致。然而,这并不重要。 您仍然可以正确地使用sizeof而不需要从头文件定义size_t。
size_t 不是必须的关键字。不同的架构通常对整数类型有不同的大小。例如,如果他们没有决定将 int 作为 64 位数据类型,那么一个 64 位机器很可能会将 unsigned long long 作为 size_t。
如果您将 sizeof 设为编译器内置类型,则会削弱进行交叉编译的能力。
此外,sizeof 更像是一个魔法编译时宏(类似于 C++ 模板),这就解释了为什么它是关键字而不是定义类型。
简单的原因是因为它不是基本类型。如果您查阅C标准,您会发现基本类型包括int
、char
等,但不包括size_t
。为什么呢?正如其他人已经指出的那样,size_t
是一种实现特定的类型(即一种能够容纳任何对象的“C字节”大小的类型)。
另一方面,sizeof
是一个(一元)运算符。所有运算符都是关键字。
size_t
是一种特定于实现的类型,但这并不是它成为库类型的原因。 - musiphil