你应该知道的GNU C语句表达式

在这里插入图片描述
许多写C语言的同道们或许都知道C语言中的表达式和语句,一般常见的语句都是在表达式后跟分号做结尾。例如,

a = 10 /*赋值表达式*/
a = 10; /*赋值语句*/

当然语句不止有这一种,暂不过多引入。

我们都知道有些表达式是有其值的,例如上面的赋值表达式,表达式的值就为10。换个例子,

a = b = 10;

在这条语句中,首先b = 10是一个赋值表达式,它确实会将10赋予变量b,但是整个表达式的值也是10,因此a的值其实就是等号后的表达式的值,即

a = 赋值表达式(b = 10)的值;

所以,a也等于10。

但是,有多少人知道,语句其实也可以反过来做表达式呢?

在这里插入图片描述
我们先附上一段这样的代码,代码可在Linux下编译通过(额外奉送汇编版strcpy,拿走不谢)。

#include <stdio.h>

#define mystrcpy(dest, src) \
    ({\
       asm("cld\n"\
           "1:\tlodsb\n\t"\
           "stosb\n\t"\
           "testb %%al, %%al\n\t"\
           "jne 1b"\
           ::"S"(src), "D"(dest)\
           :"ax");\
       dest;\
    })

int main(int argc, char *argv[])
{
    char a[1024] = {0};
    char b[] = "hello";
    printf("%s\n", mystrcpy(a, b));
	  return 0;
}

代码很简单,我想把字符串b的内容拷贝给a,然后输出出来。

这个例子中,可以看到我们的拷贝是用宏来完成的,但宏中的({…})是什么呢?

这就是我们要介绍的,语句表达式结构。

可以看到,({…})中包含了两条语句,第一条是嵌入的汇编语句asm(…);,第二条是一个简单的语句dest;。

所有在({…})中的最后一条语句必须以分号结束。且整个语句表达式的返回值就是最后一条语句中表达式的值。但如果,最后一条语句的表达式没有值,例如删掉dest;,那么整个语句表达式的值则为void。

那么上面的宏就很明了了,asm语句完成了拷贝工作,而第二条语句是为了给表达式一个值,这个值就是目的字符串的头指针。

当然,表达式语句并不一定要用在宏中,但是这样的用法在Linux早期源码中会比较常见。
在这里插入图片描述
语句表达式的存在不仅让我们可以享受如inline关键字一般的代码展开所带来的执行效率,也可以完成如块语句的多语句复杂逻辑,还可将整个逻辑给出一个返回值。这让我们的语句表达式更像一个的函数。

笔者摘自GNU C中的一段话记述了语句表达式的优点和支持范围:

This feature is especially useful in making macro definitions “safe” (so that they evaluate each operand exactly once). For example, the “maximum” function is commonly defined as a macro in standard C as follows:
#define max(a,b) ((a) > (b) ? (a) : (b))
But this definition computes either a or b twice, with bad results if the operand has side effects. In GNU C, if you know the type of the operands (here taken as int), you can define the macro safely as follows:
#define maxint(a,b)
({int _a = (a), _b = (b); _a > _b ? _a : _b; })
Embedded statements are not allowed in constant expressions, such as the value of an enumeration constant, the width of a bit-field, or the initial value of a static variable.

感兴趣的小伙伴可以在评论区一同讨论,码哥也会继续推出相关的内容,喜欢的朋友可以关注和私信码哥。

  • 20
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码哥比特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值