一 概述
二 类型
三 语句
四 函数
五 数据
六 内存
七 代码
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
1. 表达式
表达式(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论