C 是否有与 C++ 中的 std::less 等效的东西?

2023-12-21

我最近正在回答一个关于 do 的未定义行为的问题p < q在C中当p and q是指向不同对象/数组的指针。这让我想到:C++ 具有相同的(未定义的)行为<在这种情况下,还提供了标准库模板std::less保证返回与<当指针可以比较时,并在不能比较时返回一些一致的顺序。

C 是否提供了具有类似功能的功能,可以安全地比较任意指针(相同类型)?我尝试查看 C11 标准,但没有找到任何内容,但我在 C 方面的经验比 C++ 的经验要少几个数量级,所以我很容易错过一些东西。


在使用平面内存模型(基本上是所有东西)的实现上,转换为uintptr_t会正常工作。

(但请参阅在 64 位 x86 中指针比较应该有符号还是无符号? https://stackoverflow.com/questions/47687805/should-pointer-comparisons-be-signed-or-unsigned-in-64-bit-x86讨论是否应该将指针视为有符号,包括在对象外部形成指针的问题(C 中的 UB)。)

但是具有非平坦内存模型的系统确实存在,并且思考它们可以帮助解释当前的情况,例如 C++ 对于不同的内存模型具有不同的规范< vs. std::less.


部分要点<指向 C 中 UB 的单独对象的指针(或者至少在某些 C++ 修订版中未指定)是为了允许奇怪的机器,包括非平面内存模型。

一个著名的例子是 x86-16 实模式,其中指针是段:偏移量,通过形成 20 位线性地址(segment << 4) + offset。同一个线性地址可以由多个不同的 seg:off 组合来表示。

C++ std::less奇怪的 ISA 上的指针可能需要昂贵的代价,例如“规范化”x86-16 上的段:偏移量,使其偏移量 portable的方式来实现这一点。标准化所需的操作uintptr_t(或指针对象的对象表示)是特定于实现的。

但即使在使用 C++ 的系统上std::less一定很贵,<不一定是。例如,假设一个“大”内存模型,其中一个对象适合一个段,<可以只比较偏移部分,甚至不用理会段部分。 (同一对象内的指针将具有相同的段,否则它是 C 中的 UB。C++17 更改为仅“未指定”,这可能仍然允许跳过规范化并仅比较偏移量。)这是假设所有指针都指向任何部分一个对象总是使用相同的seg值,永远不会标准化。这就是您期望 ABI 对“大”而不是“巨大”内存模型的要求。 (看评论里讨论 https://stackoverflow.com/questions/58322107/does-c-have-an-equivalent-of-stdless-from-c/58332627#comment103050729_58332627).

(例如,此类内存模型的最大对象大小可能为 64kiB,但最大总地址空间要大得多,可以容纳许多此类最大大小的对象。ISO C 允许实现对对象大小进行限制,该限制低于最大值(无符号)size_t可以代表,SIZE_MAX。例如,即使在平面内存模型系统上,GNU C 也将最大对象大小限制为PTRDIFF_MAX因此大小计算可以忽略有符号溢出。)请参阅这个答案 https://stackoverflow.com/questions/9386979/what-is-the-maximum-size-of-an-array-in-c/9387041#9387041以及评论里的讨论。

如果你想允许大于段的对象,你需要一个“巨大”的内存模型,在执行时必须担心指针的偏移部分溢出p++循环遍历数组,或者进行索引/指针算术时。这会导致到处代码变慢,但可能意味着p < q碰巧适用于指向不同对象的指针,因为针对“巨大”内存模型的实现通常会选择始终保持所有指针标准化。看什么是近指针、远指针和大指针? https://stackoverflow.com/questions/3575592/what-are-near-far-and-huge-pointers- 一些用于 x86 实模式的真实 C 编译器确实有一个选项来编译“巨大”模型,其中所有指针默认为“巨大”,除非另有声明。

x86 实模式分段并不是唯一可能的非平坦内存模型,它只是一个有用的具体示例,用于说明 C/C++ 实现如何处理它。在现实生活中,实施扩展了 ISO C 的概念far vs. near指针,允许程序员选择何时可以只存储/传递相对于某些公共数据段的 16 位偏移部分。

但纯 ISO C 实现必须在小型内存模型(除了具有 16 位指针的同一 64kiB 中的代码之外的所有内容)或大型或巨大(所有指针均为 32 位)之间进行选择。有些循环可以通过仅增加偏移部分来优化,但指针对象无法优化为更小。


如果您知道任何给定实现的神奇操作是什么,您可以用纯 C 实现它。问题在于不同的系统使用不同的寻址,并且任何可移植宏都没有对细节进行参数化。

或者也许不是:它可能涉及从特殊的段表或其他东西中查找某些内容,例如就像x86保护模式而不是实模式一样,其中地址的段部分是索引,而不是要左移的值。您可以在保护模式下设置部分重叠的段,并且地址的段选择器部分甚至不一定按照与相应段基地址相同的顺序进行排序。如果 GDT 和/或 LDT 未映射到进程中的可读页面,则在 x86 保护模式下从 seg:off 指针获取线性地址可能会涉及系统调用。

(当然,x86 的主流操作系统使用平面内存模型,因此段基数始终为 0(除了使用线程本地存储)fs or gs段),并且只有 32 位或 64 位“偏移”部分用作指针。)

您可以手动添加各种特定平台的代码,例如默认情况下假设平坦,或者#ifdef检测 x86 实模式和分割的东西uintptr_t分为 16 位半部分seg -= off>>4; off &= 0xf;然后将这些部分组合回 32 位数字。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C 是否有与 C++ 中的 std::less 等效的东西? 的相关文章

随机推荐

  • 我应该使用哪种算法进行信号(声音)一类分类?

    Update我总结了问题及其答案here https jaderdias github io posts signal one class classification 我的目标是检测噪声信号中给定模式的存在 我想检测一种用麦克风记录声音的
  • 无论 Zsh 中的上下文如何,都将密钥绑定到完整的文件名

    有时我想要一个文件名 而不是 zsh 为我猜测的文件名 例如 我有一个 PNG 文件 没有正确的 png后缀 这会让 zsh 认为它不是图片 并且在我输入时不会列出它Tab完成论证display 我想知道是否有一个关键序列可以在上下文所在的
  • 如何在WebFilter的实现中获取路径变量? (服务器网络交换)

    我在 Spring Reactive 应用程序中工作 我知道如何使用 HttpServletRequest 在拦截器中获取 PathVariable 有些类似 request getAttribute HandlerMapping URI
  • 如何使 LWP::UserAgent 看起来像另一个浏览器?

    这是我关于 SO 的第一篇文章 所以要温柔 我什至不确定这是否属于这里 但就在这里 我想访问我的一个个人帐户上的一些信息 该网站写得不好 需要我手动输入我想要的信息的日期 这确实是一种痛苦 我一直在寻找一个学习更多 Perl 的借口 所以我
  • 带有参数的量角器“addMockModule()”在 Firefox 中无法正确处理结构化数据

    我最近阅读了有关这些量角器问题的解决方案 无法轻松地将上下文传递给addMockModule 695 https github com angular protractor issues 695 feat addMockModule 添加第
  • Angular ng-click 不适用于 $compile

    我有类似于下面的代码来触发clickAngular 应用程序中的事件 为什么事件没有触发 var app angular module myApp app directive myTop function compile return re
  • Scala问题可选构造函数

    想象一下这段简单的代码 class Constructor var string String def this s String this string s def testMethod println string testMethod
  • 如何在xamarin中浏览sqlite数据?

    我的应用程序中有一个列表视图 一些数据在填充列表视图之前保存到数据库中 我的问题是看不到数据 以及如何验证数据是否存储在数据库中 我给出了 Visual Studio 2015 的解决方案 适用于 Xamarin 找到上图中提到的数据库文件
  • Twitter4j:调用 getFollowersIDs 时出现不一致的身份验证错误

    我正在使用 Twitter4j 版本 3 0 3 我正在尝试提取关注者 ID 并使用 OAuth 我已经使用 Twitter4j 多年 并且对该框架比较有经验 然而 奇怪的事情发生了 我的程序将运行良好 然后间歇性地抛出以下堆栈跟踪 Exc
  • 如何从照片自定义相册中获取图像,iOS SDK?

    I m working on an iOS app in which I need gallery view like Instagram I have added gallery View camera View and video Vi
  • 使用命令行参数运行 webpack

    我一直在尝试将 args 从命令行传递到 webpack 插件 我可以通过 process argv 访问参数 但之后 wwebpack 失败并出现错误 未找到条目模块中的错误 错误 无法解析模块 看来 webpack 将 args 视为它
  • 滑动窗口操作的 Numpy 矢量化

    我有以下 numpy 数组 arr 1 1 2 3 4 5 6 3 X 2 arr 2 0 5 0 6 0 7 0 8 0 9 1 0 1 1 1 2 1 3 1 4 5 X 2 arr 1显然是一个3 X 2数组 而arr 2 is a
  • 实体框架对导航属性的约束

    我想限制导航属性返回的模型 例如 我正在使用AuditInfo模型来记录模型的活动 一旦模型被删除DeletedBy and Deleted属性已设置 然而 由于数据库中没有真正 删除 任何内容 因此这些模型仍将填充在其他模型引用的导航属性
  • 如何在 Google Apps 脚本中检查拼写和语法

    如何删除 Google 表格中包含拼写或语法错误的所有行 我更喜欢通过 Google Apps 脚本来完成此操作 我考虑过的 使用 工具 菜单中的拼写检查器太慢了 因为我已经 几万行 我发现了this https stackoverflow
  • ProgramData 和 AppData 有什么区别?

    我需要为我的程序存储一些特定于用户的配置数据 Application Data AppData 在用户目录中 和 ProgramData 在系统驱动器的根目录中 似乎都是放置它的合理位置 程序数据和应用程序数据有什么区别 我应该使用哪一个
  • 查找具有重复值的字典键

    some dict firstname Albert nickname Albert surname Likins username Angel 我想返回我的字典的键 其中它们的值存在不止一次 有人可以告诉我如何实现这一点吗 a list
  • select()系统调用中nfds=0时发生了什么

    我正在 Linux 上调试一个应用程序 它有几个线程定期调用select系统调用 strace shows select 0 NULL NULL NULL 1 342414 So nfds 0 我认为 nfds 是任何集合中出现的最高文件描
  • Chrome 自动完成多个电子邮件字段

    我的表单上有 3 个输入框 Google Chrome 提供自动完成功能 因此 如果您单击其中任何一个或开始输入内容 您将看到 Chrome 选项列表 但当您在这些自动完成选项之间上下移动时 3 个输入框将填充值 而不是当前的文本框 htt
  • Android:本地化标准文本,例如确定、取消和 GPS 未激活 - 例如?

    我希望本地化我的应用程序 当然 我需要本地化特定于我的应用程序的文本 但是标准文本是否存在一些标准资源 例如 确定 和 取消 GPS 未激活等 或者我必须完全本地化所有内容吗 android 是否附带了一些全局文本资源 我如何访问它 提前致
  • C 是否有与 C++ 中的 std::less 等效的东西?

    我最近正在回答一个关于 do 的未定义行为的问题p lt q在C中当p and q是指向不同对象 数组的指针 这让我想到 C 具有相同的 未定义的 行为 lt 在这种情况下 还提供了标准库模板std less保证返回与 lt 当指针可以比较