返回介绍

1. 表达式

发布于 2024-10-12 21:58:08 字数 1672 浏览 0 评论 0 收藏 0

表达式(expression)用于求值,计算结果为表达式类型(或 void)。

左值,右值

左值(lvalue)表示占据内存,可识别存储位置(取内存地址)的对象,如变量名;右值(rvalue)则是不表示存储位置的对象表达式(如字面量、表达式、表达式临时变量等)。

可以将 Lvalue 理解为定位(Location),Rvalue 对应读取(Read)。

两者区别的关键是:能否获取内存地址。

如此, ptr*ptr 是左值,都指向一个对象。而 ptr + 1*ptr + 1 都是返回一个值,只能是右值。

a = b;    // 读取 b 对象数据,存储到 a 内存位置。
4 = var;        // 错误!
(var + 1) = 4;  // 错误!

左值并不特指 “赋值操作左边的值”,因为 const 会阻止赋值操作。

const int a = 10;  // 左值
a = 10;            // 不能赋值!

左值可出现在右值表达式中,但右值不能直接当作左值,除非其操作能获取地址。

int a = 1;      // 左值
int b = 2;      // 左值
int c = a + b;  // 加法表达式返回右值
int d[]  = {1, 2};
int* p   = d;
*(p + 1) = 10;   // p + 1 是右值,但 *(p + 1) 是左值。

复合字面量

构造指定类型的无名对象,可直接返回指针。

struct data {
    int x;
};

void test (int x, struct data *d)
{
    printf("test x = %d, d.x = %d\n", x, d->x);
}

int main (void)
{
    int *i = &(int) { 10 };             // 整数,指针
    int *x = (int[]) { 1, 2, 3, 4 };    // 数组

    assert(*i == 10);
    assert(x[2] == 3);

    assert((struct data) { .x = 100 } .x == 100); // 结构体
    test(123, &(struct data) { .x = 123 });       // 结构体,指针

    return 0;
}

泛型选择

根据参数类型,在编译期选择表达式。

_Generic( arg_expr, type_name:expression 
                   [type_name: expression, ... ,] 
                   [default: expression)

其中,default 可选,不能有多个。

类型名称(type_name)必须是互不兼容的不同类型。

不允许不完整类型和可变长度数组类型。

bool x = true;
int  a = _Generic(x, _Bool: 100, default: 0);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文