C 参考手册
- C 语言
- C 的历史
- 基本概念
- 表达式
- 声明
- 初始化
- 函数
- 语句
- 静态断言
- 字符常量
- 函数声明
- 函数定义
- 转义序列
- 翻译阶段
- 标识符
- 作用域
- 生存期
- 查找与命名空间
- ASCII 码表
- 类型
- 遵从性
- 算术类型
- restrict 类型限定符
- 类型
- 对象与对齐
- 主函数
- 未定义行为
- 内存模型
- if 语句
- switch 语句
- for 循环
- while 循环
- do-while 循环
- continue语句
- break 语句
- goto语句
- return 语句
- 值类别
- 求值顺序
- 整数常量
- 浮点常量
- 字符串字面量
- 复合字面量
- 常量表达式
- 隐式转换
- 成员访问运算符
- 逻辑运算符
- 比较运算符
- 算术运算符
- 赋值运算符
- 自增/自减运算符
- 其他运算符
- sizeof 运算符
- _Alignof 运算符
- 转型运算符
- C 运算符优先级
- 泛型选择
- 标量初始化
- 数组初始化
- 结构体与联合体初始化
- 指针声明
- 数组声明
- 枚举
- 存储类指定符
- const 类型限定符
- volatile 类型限定符
- 结构体声明
- 联合体声明
- 位域
- _Alignas
- typedef 声明
- 原子类型
- 外部及试探性定义
- inline 函数指定符
- _Noreturn 函数指定符
- 变长参数
- 内联汇编
- 可分析性
- 替用运算符及记号
- C 关键词
- 预处理器
- C 标准库头文件
- 类型支持
- 程序支持工具
- 变参数函数
- 错误处理
- 动态内存管理
- 日期和时间工具
- 字符串库
- 算法
- 数值
- 文件输入/输出
- 本地化支持
- 原子操作库
- 线程支持库
- 实验性 C 标准库
- 有用的资源
- 符号索引
- 注释
值类别
C中每个表达式(带有参数的运算符、函数调用、常量、变量名等)以两个独立属性刻画:类型和值类别。
每个表达式属于三个值类别之一:左值、非左值对象(右值)以及函数指代器。
左值表达式
左值表达式是任何类型异于 void
的对象类型,且隐含地指代一个对象的表达式(当左值在求值时不实际指代一个对象时,行为未定义)。换言之,左值表达式求值得到对象标识。此值类别的名称(“左值”)是历史性的,并反映了 CPL 中,左值表达式作为赋值运算符的左运算数。
左值表达式可用于下列左值语境:
若将左值表达式用于异于 sizeof 、 _Alignof 或上述的运算符,则任何完整类型的非数组左值会经历左值转换,这模仿的是从对象位置到其值的内存加载。同样地,在用于异于 sizeof
、 _Alignof
、取址运算符或从字符串字面量初始化数组的语境时,数组左值会经历数组到指针转换。
const/volatile/restrict 限定符和原子类型的语义仅应用于左值(左值转换将剥除限定符并移除原子属性)。
下列表达式是左值:
- 标识符,含函数参数,只要他们被声明为指代对象(而非函数)
- 字符串字面量
- (C99) 复合字面量
- 括号表达式,若其无括号版本是左值
- 成员访问(点)运算符的结果,若其左参数是左值
- 由指针访问成员(
->
)运算符的结果 - 间接使用运算符(一元
*
)作用域指向对象指针 - 下标运算符的结果(
[]
)
可修改左值表达式
一个可修改左值是任何完整类型、非数组、且非 const 限定的左值表达式,而且若它是结构体/联合体,则递归地没有任何成员为 const 限定。
只有可修改左值表达式可用作自增减运算符的参数,赋值和复合赋值运算符的左参数。
非左值对象表达式
通称为右值,非左值表达式是不指代对象的对象类型表达式,而是没有对象身份或存储位置的值。不能对非左值表达式取址。
下列表达式是非左值对象表达式:
- 整数、字符、浮点数常量
- 所有不返回左值的运算符,包括
- 任何函数表达式
- 任何转换类型表达式(注意看起来相似的复合字面量是左值)
- 作用于非左值结构体/联合体的的成员访问(点)运算符,f().x、 (x,s1).a、 (s1=s2).m
- 所有算术、关系、逻辑及位运算符
- 自增和自减运算符(注意:前置形式在 C++ 中是左值)
- 赋值及复合赋值运算符(注意:它们在 C++ 中是左值)
- 条件运算符(注意:在 C++ 中可能是左值)
- 逗号运算符(注意:在 C++ 中可能是左值)
- 取址运算符,即使它被用一元
*
运算符的结果中和
作为特殊情况, void
类型表达式被假设成非左值对象表达式,得出一个不存在表示且不要求存储的值。
注意,拥有一个数组类型成员(可以是嵌套的)的结构体/联合体右值实际上指代一个拥有临时生存期的对象。此对象可通过由索引数组元素组成的左值表达式,或解引用该数组的数组到指针转换所得的指针访问。
函数指代器表达式
函数指代器(由函数声明引入的标识符)是函数类型的表达式。当在异于取址运算符、 sizeof 及 _Alignof (后两者在作用于函数时生成编译错误)的语境中时,函数指代器始终转换成指向函数的非左值指针。注意函数调用运算符是对指向函数指针,而非对函数指代器自身定义的。
引用
- C11 standard (ISO/IEC 9899:2011):
- 6.3.2.1 Lvalues, arrays, and function designators (p: 54-55)
- C99 standard (ISO/IEC 9899:1999):
- 6.3.2.1 Lvalues, arrays, and function designators (p: 46)
- C89/C90 standard (ISO/IEC 9899:1990):
- 3.2.2.1 Lvalues and function designators