sizeof
是一个 C关键字。它以名为 的类型返回大小size_t
。但是,size_t
不是关键字,而是主要在stddef.h
可能还有其他 C 标准头文件中定义。
考虑一个场景,您想要创建一个不包含任何 C 标准头文件或库的 C 程序。(例如,如果您正在创建 OS 内核。)现在,在这样的代码中,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
是一个关键字,因为尽管它有名称和用法,但它是一个类似or or的运算符,而不是类似or or的函数。很多人忘记(或只是不知道)它实际上是一个运算符,并且总是在编译时而不是在运行时解析。+
=
<
printf()
atoi()
fgets()
sizeof
C 语言不需要size_t
是一种可用的、一致的语言。这只是标准库的一部分。C 语言需要所有运算符。如果+
C 使用关键字plus
来添加数字,而不是 ,则将其设为运算符。
此外,我一直在将 s 半隐式重铸为size_t
s unsigned int
(以及常规int
s,但 Kernighan 和 Ritchie 总有一天会为此而惩罚我)。如果愿意,您可以将 a 的返回类型分配给sizeof
int,但在我的工作中,我通常只是将它直接传递给 amalloc()
或其他东西。
C 标准中的一些头文件是为独立环境定义的,即适合在操作系统内核中使用。它们不定义任何函数,仅定义和 typedef。
它们是 float.h、iso646.h、limits.h、stdarg.h、stdbool.h、stddef.h 和 stdint.h。
在操作系统上工作时,从这些标头开始并不是一个坏主意。让它们可用会使你的内核中的许多事情变得更容易。尤其是 stdint.h 会变得很方便(uint32_t 等)。
这不是表示 C 标准规范中存在某种问题吗?
查找 C 的托管实现和独立 C 实现之间的区别。独立式 (C99) 实现需要提供标头:
<float.h>
<iso646.h>
<limits.h>
<stdarg.h>
<stdbool.h>
<stddef.h>
<stdint.h>
这些头文件根本没有定义任何功能。它们定义了语言的某些特定于编译器的部分(例如, 中的offsetof
宏<stddef.h>
,以及 中的变量参数列表宏和类型<stdarg.h>
),但它们可以在不作为完整关键字实际构建到语言中的情况下进行处理。
这意味着即使在您假设的内核中,您也应该期望 C 编译器提供这些头文件和任何底层支持函数——即使您提供了其他所有内容。
我认为size_t
不是关键字的主要原因是:
例如,在讨论 C++ 标准的下一个主要修订版时,Stroustrup 曾这样说:
C++0x 的改进应该以这样一种方式进行,即生成的语言更容易学习和使用。委员会的经验法则包括:
...
- 喜欢标准库设施而不是语言扩展
...
没有理由不包含 stddef.h,即使您正在使用内核 - 它为您的特定编译器定义了任何代码都需要的类型大小。
另请注意,几乎所有 C 编译器都是自编译的。因此, sizeof 运算符的实际编译器代码将使用 size_t 并引用与用户代码相同的 stddef.h 文件。
size_t 实际上是一种类型 - 通常是无符号整数。Sizeof 是一个给出类型大小的运算符。sizeof 返回的类型实际上是特定于实现的,而不是 C 标准。它只是一个整数。
编辑:要非常清楚,您不需要 size_t 类型即可使用 sizeof。我认为您正在寻找的答案是 - 是的,它是不一致的。不过,没关系。您实际上仍然可以正确使用 sizeof 而无需从头文件中定义 size_t 。
来自MSDN:
当 sizeof 运算符应用于 char 类型的对象时,它产生 1
即使您没有可用/包含的 stddef.h 并且不知道 size_t,使用 sizeof 也可以获取对象相对于 char 的大小。
size_t不是必要的关键字。不同的架构通常对整数类型有不同的大小。例如,如果 64 位机器没有决定将int设置为 64 位数据类型,则它们可能具有unsigned long long as size_t 。
如果您将 sizeof 设置为编译器的内置类型,那么它将带走进行交叉编译的能力。
此外,sizeof更像是一个神奇的编译时宏(想想 c++ 模板),它解释了为什么它是一个关键字而不是定义的类型。
原因很简单,因为它不是基本类型。如果您查看 C 标准,您会发现基本类型包括int
等,char
但不包括size_t
。为什么这样?正如其他人已经指出的那样,size_t
它是一种特定于实现的类型(即,一种能够保持任何对象的“C 字节”数量大小的类型)。
另一方面,sizeof
是(一元)运算符。所有运算符都是关键字。