关于`size_t`和它们测量的指针类型

时间:2016-08-07 19:08:49

标签: c pointers types typedef

如果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是不合需要的?好像应该没问题。据我所知,指针保证占据寄存器的全部大小,因此应该与体系结构的大小相同&#34;理想的&#34; size_t

2 个答案:

答案 0 :(得分:8)

  

size_t未定义时,它是唯一可移植的方式   它的定义是包含一个包含它的标题。

正确。

  

但是,据我所知,在头文件中使用#include是不好的   练习,因为标题不应该包含其他标题,对吗?

你被误导了。没有理由不在其他标头中包含标头。多个#include的相同标头可能会导致问题如果他们没有正确的包含警卫,但标准标头保证有这样的警卫(或等效的) - 和非标准标题应该有这样的警卫。 (<assert.h>是一个特例。)

如果您在源文件或头文件中需要size_t,则应使用#include <stddef.h>使名称size_t可见(或者您可以包含其中一个其他标准标题也使size_t可见。

在标题中包含<stddef.h>会使其声明在包含标题的任何其他文件中都可见,但这不是问题。

  

据我了解,size_t类型是保证的最小类型   支持系统可以处理的最长对象。

这是一个无符号整数类型,由实现选择保存大小值。它应该能够保持任何对象的字节大小(虽然没有明确保证)。不能保证它是最小的这样的类型,假设它没有任何好处。

  

对于指针,任何给定的指针都代表从0开始的偏移量   RAM中的字节,取消引用该偏移量将为您提供值   存储在该偏移处。
[...]因此,不是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。但是,定义比编译器#include 更宽的您自己的类型既没有用也没必要。如果您稍后为正确定义size_t的几个标准标头之一添加typedef char * size_t // I like this one...but am not 100% sure about how portable it is (或者包含其中一个标头的标头),则会产生冲突

size_t

绝对不是。 "start": "nodemon -e ts --exec \"npm run myapp\"", "myapp": "tsc -p . && node server.js", 必须是无符号整数类型。如果你被告知整数和指针是可以互换的,你就会被误导。

答案 1 :(得分:1)

如果您需要size_t,则需要包含stddef.h,就像P.P.在评论中说。标准中size_t的定义:

  

ISO / IEC 9899-2011秒。 7.19&#34;通用定义&#34;

     

size_t是sizeof运算符

结果的无符号整数类型

此外,size_t的大小在宏

中定义
  

ISO / IEC 9899-2011秒。 7.20   SIZE_MAX 65535

(数字65535是最小尺寸)

因此,无论如何,您都需要包含stddef.h