什么时候确定指针差异?

 皮皮美2_160 发布于 2023-02-11 18:20

我有一个关于指针差异和结果类型的问题ptrdiff_t.

C99§6.5.6(9)说:

当减去两个指针时,两个指针都指向同一个数组对象的元素,或者指向数组对象的最后一个元素的元素; 结果是两个数组元素的下标的差异.结果的大小是实现定义的,其类型(有符号整数类型)ptrdiff_t在头文件中定义.如果结果在该类型的对象中无法表示,则行为未定义.换句话说,如果表达式P和Q分别指向数组对象的第i和第j个元素,则表达式(P) - (Q)具有值i-j,条件是该值适合于对象类型ptrdiff_t.

§7.18.3(2)要求ptrdiff_t的范围至少为[-65535,+ 65535]

我感兴趣的是如果结果太大则未定义的行为.我无法在标准版本中找到任何与签名版本size_t或类似内容相同的范围.所以,现在我的问题是:符合标准的实现是否可以生成ptrdiff_t带符号的16位类型但size_t64位?[编辑:正如Guntram Blohm指出的那样,16位签名最多为32767,所以我的例子显然不符合]据我所知,我不能在严格符合代码甚至超过65535个元素的数组上做任何指针减法如果实现支持比这大得多的对象.此外,该程序甚至可能崩溃.

理由(V5.10)§6.5.6说:

重要的是要对这个类型[ ptrdiff_t]进行签名,以便在处理同一数组中的指针时获得适当的代数排序.但是,指针差异的大小可以与可以声明的最大对象的大小一样大; 由于这是一个无符号类型,两个指针之间的差异可能会导致某些实现溢出.

这可以解释为什么不需要指定每个指针差异(对同一个数组的元素),但它不能解释为什么PTRDIFF_MAX至少没有限制SIZE_MAX/2(使用整数除法).

为了说明,假设T是任何对象类型和编译时未知n的对象size_t.我想为n对象分配空间T,我想用指定范围内的地址进行指针减法.

size_t half = sizeof(T)>1 ? 1 : 2; // (*)
if( SIZE_MAX/half/sizeof(T)

我不得不严格遵守

if( SIZE_MAX/sizeof(T) < n || PTRDIFF_MAX < n )

代替.真的那样吗?如果是这样,有人知道原因(即不需要PTRDIFF_MAX >= SIZE_MAX/2[编辑:更改>>=]或类似的东西)?

(*)第一个版本中的一半是我在写这篇文章时认出的东西,我有

if( SIZE_MAX/2/sizeof(T) < n )

首先,用一半SIZE_MAX来解决基本原理中提到的问题; 但后来我意识到SIZE_MAX只要sizeof(T)是1,我们只需要减半.鉴于这个代码,第二个版本(肯定是严格符合的版本)似乎并不那么糟糕.但是,如果我是对的,我仍感兴趣.

C11保留了§6.5.6(9)的措辞,C++相关的答案也很受欢迎.

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有