类型为size_t和ptrdiff_t的变量

20

通过阅读与 size_t 和 ptrdiff_t 相关的帖子,我想确认以下内容:

  1. 如果数组的最大大小小于 1/2*(max number represent-able by size_t),那么我可以安全地使用 ptrdiff_t 并检查同一对象的两个指针之间的相对距离吗?(由于我在谈论数组,所以“指向同一对象的指针”表示“指向同一数组的指针”)。

  2. 如果我想声明一个变量来表示另一个指针的偏移量,我最好将其声明为类型 ptrdiff_t 吗?

  3. 如何在 C 和 C++ 中输出类型为 size_t ptrdiff_t 的变量?以下是否正确:交叉平台格式化字符串以处理类型为size_t的变量?

  4. uintptr_t 只是 size_t 的另一个名称,还是应该将其用作与 size_t 不同的单独类型?

  5. ssize_tintptr_t 是否是 ptrdiff_t 的另一种名称,还是必须以不同的方式使用?

我开始在 Ubuntu 上使用 gcc。当使用别人的代码时,我才发现这些类型。

ADDed: 我确实希望能够使用负偏移量。 uintptr_tintptr_t 使用上有任何差异吗?


1
@MooingDuck: ssize_t 是一个Posix类型 (例如,在readwrite的返回类型中使用)。_ptrdiff_t_看起来像是一个打字错误。 - Mike Seymour
@MooningDuck:对于_ptrdiff_t_,我只是想尝试一下它是否被斜体化了。刚刚删除了该词周围的下划线。 - Rich
@Mike:在C或C++中,Posix类型和常规类型内置之间有什么区别?我可以互换使用吗? - Rich
在我看来,你好像重新问了一堆已经在这里得到回答的问题,然后又问这些答案是否正确。你为什么要怀疑之前的答案?这篇文章提出了什么新的问题? - Rob Kennedy
显示剩余5条评论
3个回答

20

1: 如果一个数组的最大大小小于 1/2*(size_t 所能表示的最大值),我可以安全地使用 ptrdiff_t 并检查指向同一对象的两个指针之间的相对距离吗?

如果 sizeof(size_t) <= sizeof(prtdiff_t),那么是这样的。在合理的实现中应该是这种情况,但不能保证。

2: 如果我想声明一个变量来表示另一个指针的偏移量,最好将其声明为 ptrdiff_t 类型吗?

是的,这就是该类型的预期用途。

3: 如何在 C 和 C++ 中输出 size_tptrdiff_t 类型的变量?

在 C 中:

printf("%zu %td\n", size, ptrdiff);

在C++中:

std::cout << size << ' ' << ptrdiff << '\n';

4: uintptr_t是另一个名称的size_t还是应该作为与size_t不同的类型使用?

应将其视为单独的类型。uintptr_t是一种整数类型,可以包含转换为整数的任何指针值;在某些平台上可能不存在。

5: ssize_tintptr_tptrdiff_t的另一个名称,还是必须以不同方式使用?

ssize_t并不是C或C++语言中的标准类型;它由Posix定义为某些函数参数和返回值的类型。最好使用ptrdiff_t,除非直接处理Posix函数。

intptr_t用于保存指针的整数表示,而不是指针之间的差异。在某些平台上,它们可能具有不同的大小,并且intptr_t可能根本没有定义,因此不能互换使用。

我想要能够使用负偏移量。是否有任何使用uintptr_tintptr_t的区别?

不要使用这些类型来表示偏移量;使用ptrdiff_t。在特殊情况下,当您想以某种原因将指针转换为其整数表示时,请使用这些类型。


2
如果您只需要处理基指针的正偏移量(这在我所做的工作中经常发生),则可以使用size_t而不是ptrdiff_t。如果可能需要负偏移量,则应使用ptrdiff_t - Jonathan Leffler
在某些平台上,ptrdiff_t 可能与 intptr_t 不同;在许多平台上,它们将由相同的类型表示。 - Jonathan Leffler
当你需要使用其中之一时,你如何决定是使用intptr_t还是uintptr_t - user541686
@Mehrdad:如果你不对转换后的值进行算术运算,那么这就无关紧要了。如果你确实需要进行运算,那么你已经离开了理智的领域,但是无符号算术可能会稍微好一些。 - Mike Seymour
挑剔一下:如果我没记错的话,不能保证 std::cout << size << ' ' << ptrdiff << '\n'; 能正常工作。size_t 没有 ostreamable 的保证。 - L. F.
显示剩余2条评论

1

uintptr_tintptr_t足够大,可以容纳任何void*指针值而不会丢失信息。它们需要能够唯一地表示程序整个地址空间中任何对象的地址,包括任何对象内的任何字节。

size_t是由sizeof运算符产生的类型;ptrdiff_t是通过减去两个指针产生的类型。它们只需要足够大以容纳单个对象。(并且可能存在一个对象非常大,使得减去指向相反端点的两个指针将溢出的情况。)

大多数当前系统具有单个整体地址空间,但C语言设计用于在不具备此类特性的系统上工作。例如,在某些系统上,最大可能的对象大小可能只是整个地址空间大小的一小部分,比较或减去指向不同对象的指针可能是没有意义的。(考虑分段寻址方案,其中指针减法和比较仅考虑地址的偏移量部分。)


0

假设_ptrdiff_t_是一个打字错误:

1)是的。如果数组的最大大小小于SIZE_MAX/2,您可以安全地使用ptrdiff_t
2)有时候:ptrdiff_t通常是两个指针之间的差异,而size_t是一个偏移量。重要的是size_t始终为正数,ptrdiff_t可能为负数。请注意,在某些平台上,它们的大小可能相差很大。
3)您以与输出任何其他变量类型相同的方式输出size_tptrdiff_t类型的变量。

size_t a = 10;
ptrdiff_t b = 20;
printf("%u %d", ((unsigned int)a), ((int)b));
std::cout << a << b;

4) uintptr_t 是一个无符号整数,至少和 int* 一样大,可以安全地对指针进行整数运算。size_t 据我所知并没有保证大小相同。
5) ssize_t 是一个非标准的 C 类型,对应于 ptrdiff_t。请使用 ptrdiff_t。(对于支持 POSIX 1003.1-1996 API 标准的平台(包括大多数类 Unix 系统),有一个名为 ssize_t 的 size_t 有符号变体可用,这不是 ANSI 或 ISO C 标准的一部分。http://en.wikipedia.org/wiki/Size_t


1
我认为 ssize_t 对于 ptrdiff_t 来说并不是非标准的。它通常被用作从读/写例程返回的“字节数或错误”计数。 - user7116
我知道一个平台,其中size_t是16位,但ptrdiff_t是32位。此外,ssize_t是size_t的有符号等价类型。恰好在原始平台上,它与用于ptrdiff_t的底层类型相同。 - Joshua
1
危险:如果sizeof(size_t)或sizeof(ptrdiff_t)> sizeof(int)[两者都允许],则您的printf无法正常工作。永远不要在没有将它们先转换为基本类型的情况下将size_t或ptrdiff_t传递给printf。 - Joshua
如果我想使用既可以是正数也可以是负数的偏移量,我应该使用 ptrdiff_t 吗?这样正确吗?我刚刚编辑了我的问题。有一个链接介绍如何输出这些类型。链接。那个特殊的格式正确吗? - Rich
ssize_t 是 POSIX 类型;它是 read()write() 和相关函数返回的值。 - Jonathan Leffler
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接