我被迫将IAR EW430编译器v7.12用于嵌入式项目,并且它仅正式支持c99。
除了编写一堆专用的内联函数之外,我希望能够通过任何其他方式通用地模拟GCC的语句表达式。
有什么办法可以做到这一点? (也许使用MACRO-wizardry?还是仿真Lambda,或者某些允许这样做的隐藏编译器开关?)显然,除了更改编译器。
具体来说,复合表达式的最后一条语句的结果应同时携带其类型和值,而不能将其作为宏参数传入。
我已经搜索了几个月,但是最接近的是令人印象深刻的impressive library,但是这似乎令人失望。
答案 0 :(得分:4)
我意识到这不是您要寻找的答案,但是既然您问“有没有办法实现这一目标?”,我不得不说答案就是“否”。
别误会我-我知道您在寻找什么,以及为什么要这么做。这是一个非常酷的功能。曾几何时,我试图发明自己的类似于C的语言,而我的目标之一就是使每个语句都可以用作表达式。但是,此功能根本不是C的一部分,并且没有可模仿的方法。
实际上,您可以很容易地证明,没有什么不错的方法可以模拟它,因为如果有的话,海湾合作委员会的人们就不必实施那些疯狂的,非标准的扩展。
因此,如果您想使用gcc及其扩展名,请务必使用gcc及其扩展名。但是,如果您想用纯净的C语言编写代码,那么您将不得不学习没有语句表达式的生活。 “在罗马做到入乡随俗。”您使用疯狂的宏魔术所设法实现的任何事情都可能(a)不能真正满足您对真正的语句表达式的渴望,并且(b)使得程序的维护对于任何追随您并且不了解它们的优点的人来说都是噩梦
您说您正在做嵌入式工作,但是您确定平台没有gcc端口吗? (我知道您说过您被迫“使用” IAR,但是您也说这是一个“玩具项目”,所以也许您可以打破该规则。IAR总是让我想到维基百科的口号“忽略所有规则” 。:-))
但是,由于您说过您正在做嵌入式工作,所以这是阻止这种过时的Featurephilia的另一个原因。我得到的印象是,“嵌入式工作”的定义特征之一是,无论如何它都试图拒绝使用一半的语言,仅要求使用定义非常明确,非常安全的子集。因此,我怀疑像语句表达式这样的扩展是否会为您的项目所用。
答案 1 :(得分:1)
在评论中,您需要澄清
我的目的是真正(或尽可能紧密地)模仿陈述 表达式,应尽可能以各种方式使用 他们拥有的财产。
因此,让我们看一下语句表达式的形成方式及其作用:
括在括号中的复合语句可能显示为 GNU C中的表达式。这允许您使用循环,开关和局部 表达式中的变量。
[...]
复合语句中的最后一件事应该是表达式 其次是分号;该子表达式的值用作 整个构造的价值。
有两个关键部分:
该构造基于复合语句,因此可以包含在复合语句可以包含的任何内容中。
该构造的结果为一个值。
此外,您明确地说
具体来说,该化合物的最后一个语句的结果 表达式应同时携带其类型和值,而不要包含那些 作为宏参数传入。
您已将自己画在一个角落。 C语句不是表达式,这恰恰意味着它们不求值。这就是为什么GCC语句表达式是扩展的原因。值没有链接,并且在一定程度上可以认为它们具有范围,它仅限于它们出现的表达式和存储它们的对象。从语句中转移值的唯一方法是将其分配给适当类型的对象(并且您显然想避免这样做)或return
对其进行赋值(这要求它在函数中)。
语句表达的其他特征可能首先吸引了您的兴趣。特别是,由于您提出了lambda,我怀疑您对以下事实感兴趣:语句表达式位于周围代码的上下文中,因此除其他事项外,它们可以使用范围内的标识符。如果您要这样做,那么您可能只需要编写普通的代码块,并提供用于报告结果的变量即可。
但是,还有另一种选择可以给您一些您的追求。您可以依次计算几个表达式,每个表达式都可以使用逗号运算符来利用先前表达式的副作用。例如,
int first = 1, second = 2, temp, new_first;
new_first = (temp = second, second = first, first = temp);
结果是交换first
和second
的值,并将得到的first
的新值分配给new_first
。当然,这不提供循环,if
语句, etc ,并且它尤其不提供声明局部变量,例如temp
。正如我所说的,一些语句可以做什么。