为什么GCC的三元扩展不支持赋值?

2024-05-24

海湾合作委员会有一个很棒的 C 三元表达式扩展 http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Conditionals.html#Conditionals这允许我们创建这样的语句:

int x = some_var ?: 10; // expands to some_var ? some_var : 10

这真的很好,虽然不是特别直观,但确实有效。 C 语言中的大多数二元运算符都有一个与之关联的附加运算符,它允许赋值:

x = x + 2;

// instead, we can say
x += 2;

既然是这种情况,并且大多数二元 C 运算符的规范 (+, -, *, /, %, |, &, ^),为什么三元扩展运算符不是这种情况:

int x = ...;
x ?:= 2; // error: Expected expression before '=' token

// which would expand to
x = x ?: 2;

唯一的运营商don't标准 C 中支持这一点的是逻辑运算符 (||, &&),三元绝对不属于这个范围,那么为什么我们不能这样做呢?

我真的很想在我的代码中制作一个带有很酷发型的笑脸,但我不能!这是设计操作员时的疏忽,还是有意为之并在某处记录?这是运算符短路其操作数的结果,还是完全是其他原因?


为了回答这个问题,我相信还需要回答一些其他问题。

为什么有一个?:C 语言中的运算符以及为什么它更好 比if-else?

据我所知,除了陈述自己的主观意见外,没有人能够回答这个问题。 K&R 2.11 指出

“条件表达式通常会产生简洁的代码。”

然后他们用这一行来说明这一点

printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');

这是他们自己主观的、模糊的意见。就我个人而言,我相信

printf("%6d", a[i]);

if(i%10==9 || i==n-1)
  printf("\n");
else
  printf(" ");

更加清晰,因为我可以在 10 秒内阅读和理解该代码,而不是花 1 分钟阅读和理解 K&R 版本。另外,我的代码将整数打印与不相关的格式分开。但当然,那就是my主观意见,没有明显的对错。

至于官方消息,C99 基本原理版本 5.10、6.5.15 也没有真正提到为什么需要 ?: 运算符。它主要只是说明新标准中操作员的行为发生了变化:

条件语句中间操作数的语法限制 运营商已经放宽,包括的不仅仅是 逻辑或表达式:几个现有的实现已采用 这种做法。

条件运算符表达式的类型可以是 void、a 结构或联合;大多数其他运营商不处理此类问题 类型。平衡指针和整数之间的类型的规则有, 然而,已经收紧了,因为现在只有常量 0 可以移植 强制为指针。

因此,如果有人想要对结构或联合类型执行算术运算,那么 ?: 应该比 if-else 更方便。我认为这没有明显的好处,但至少这是运营商存在的一些理由。

下一个问题是:

为什么有一个编译器扩展?:GCC 中的操作数 编译器?

这个问题的答案已经提到了here http://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals:

当它变得有用时,是当第一个操作数确实或可能(如果它 是一个宏参数),包含副作用。然后重复 中间的操作数会产生两次副作用。省略 中间操作数使用已经计算出的值,无需 重新计算它会产生不良影响。

因此,这个 GCC 扩展与可读性或语言一致性无关,它只是为了避免不必要的副作用而添加的。

然后尝试回答原来的问题:

为什么GCC的三元扩展不支持赋值?

可能是因为在赋值条件下访问左值通常不会产生任何不需要的副作用。x = x ? : 2;如果 x 被声明为 a,只会产生不需要的副作用volatile- 读取易失性变量是一个副作用。所以我能看到的唯一实际用途是x ?:= 2;是为了防止有人在同一个条件表达式中两次访问同一个易失性变量。

这是一个非常狭窄且价值有限的特征。在某些特殊的嵌入式系统情况下,它可能很有用,在这种情况下,您可以在要求严格的实时系统中读取硬件寄存器……除此之外,我认为它没有任何用处。

除了传统和主观编码风格偏好之外,我也找不到任何官方或规范来源说明 ?: 运算符本身的任何用途。

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

为什么GCC的三元扩展不支持赋值? 的相关文章

  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 重载<<的返回值

    include
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex

随机推荐