[英]Regarding `size_t` and the pointer types they measure
当未定义size_t
,可以说获得其定义的唯一可移植方法是包括具有该定义的标头之一。
但是,据我所知,在头文件中使用#include
是不好的做法,因为头不应包含其他头,对吗?
因此,找到一种方法来确保头文件可以在不降低编程习惯的前提下进行编译是程序员的责任。
据我了解, size_t
类型是保证支持系统可以处理的最长对象的最小类型。 例如,如果您运行的是64位操作系统,则size_t
应该为64位,因为这就是RAM和指针自身以及自身的工作方式。
至于指针,任何给定的指针都代表从RAM中第0个字节开始的偏移量,在此引用该偏移量将为您提供存储在该偏移量处的值。 然后,CPU(在这种情况下为64位整数)被完全控制,可以访问它可以使用其支持的最大单元(也就是64位整数)寻址的任何18兆字节左右的字节。 ,又名指针。
因此,难道不保证size_t
和任何给定的指针类型都具有相同的大小吗?
那么问题是,对于给定的标头,以下哪项是最佳实践:
void some_function(ptr *some_object, size_t n);
...
可能性似乎是:
#include <stddef.h>
// would definitely work...but including a header in a header is ugly practice
typedef long long unsigned size_t
// to account for win64 making `long` 32-bits...but it's possibly non-portable
typedef char * size_t
// I like this one...but am not 100% sure about how portable it is
此外,是否有任何理由为什么不希望将指针用于size_t的定义? 看来应该没问题。 据我了解,一个指针一定是占用寄存器的全尺寸,因而应的尺寸与结构的“理想”相同size_t
当未定义
size_t
,可以说获得其定义的唯一可移植方法是包括具有该定义的标头之一。
正确。
但是,据我所知,在头文件中使用
#include
是不好的做法,因为头不应包含其他头,对吗?
您被误导了。 没有理由不在其他标头中包含标头。 如果没有适当的包含保护,则同一标头的多个#include
可能会导致问题,但是标准标头必须保证具有此类保护(或等效方法)-非标准标头应具有此类保护。 ( <assert.h>
是特例。)
如果需要在源文件或头文件中使用size_t
,则应使用#include <stddef.h>
使名称size_t
可见(或可以包含也使size_t
可见的其他标准头文件之一) 。
在头文件中包含<stddef.h>
将使它的声明在包含头文件的任何其他文件中可见,但这不是问题。
据我了解,
size_t
类型是保证支持系统可以处理的最长对象的最小类型。
这是实现选择的用于容纳大小值的无符号整数类型。 它应该能够保存任何对象的大小(以字节为单位)(尽管不能明确保证)。 不能保证它是最小的此类类型,也不能保证它是最小的类型。
至于指针,任何给定的指针都代表从RAM中第0个字节开始的偏移量,在此引用该偏移量将为您提供存储在该偏移量处的值。
[...]
因此,难道不保证size_t和任何给定的指针类型都具有相同的大小吗?
不,没有这样的保证。 在大多数现代系统上,指针确实代表虚拟地址0的字节偏移量,但这不能保证。 在具有分段内存模型的系统上,单个对象的最大大小可能比内存大小小得多; 一个指针可能包含一个段指示符和一个字节偏移量,不允许一个对象占用一个以上的段。
size_t
类型的值必须能够表示任何单个对象的大小。 指针(例如, void*
或unsigned char*
类型的指针)需要能够表示任何对象或其中任何字节的地址。
不要对指针的大小或size_t
进行任何不必要的假设。 让编译器为您解决。
可能性似乎是:
#include <stddef.h>
// would definitely work...but including a header in a header is ugly practice
不,这不是丑陋的做法。 就是这样
typedef long long unsigned size_t
// to account for win64 making `long` 32-bits...but it's possibly non-portable
这绝对是不可携带的。 size_t
甚至可能比unsigned long long
。 但是,定义比编译器的size_t
宽的自己的类型既无用也无必要。 如果以后为正确定义size_t
的几个标准标头之一(或包含这些标头之一的任何标头)添加#include
,它将产生冲突。
typedef char * size_t
// I like this one...but am not 100% sure about how portable it is
绝对不。 size_t
必须是无符号整数类型。 如果您被告知整数和指针是可互换的,那么您将被严重误告知。
如果需要size_t
,则需要包含stddef.h
,就像PP在注释中所说的那样。 标准中size_t
的定义:
ISO / IEC 9899-2011秒 7.19“通用定义”
size_t
是sizeof运算符结果的无符号整数类型
此外,在宏中定义了size_t
的大小
ISO / IEC 9899-2011秒 7.20 SIZE_MAX 65535
(数字65535为最小尺寸)
因此,无论如何,都需要包含stddef.h
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.