C语言标准:对象、类型、常量、字面量

本文中的某些关于C语言的内容与C++并不完全一致,请注意区分。


对象(Object)

对象指数据存储的区域。并不是只有C++中的 class 才被称为对象,例如:

1
2
3
int a; // a 是一个对象
int* b; // b 是一个对象
int c[6]; // c 是一个对象

C语言中其实没有变量的说法,通常说的变量准确地来说其实是对象,当然在不是很严肃的场合成为变量也无伤大雅,这里较真一下。


类型(Type)

类型决定了如何解释对象或表达式结果的值的含义。

这里先列出C语言的基本类型(方便起见,省略了几乎没人用的_Complex和_Imaginary):

  • void
  • char
  • 标准有符号整数类型(Standard signed integer type):signed charshort intintlong intlong long int(C99)
  • 标准无符号整数类型(Standard unsigned integer type):_Bool(C99),unsigned charunsigned short intunsigned intunsigned long intunsigned long long int(C99)
  • 标准有/无符号整数类型统称标准整数类型(Standard integer type)
  • 扩展有符号整数类型(Extended signed integer type)和扩展无符号整数类型(Extended unsigned integer type),统称扩展整数类型(Extended integer type),这是由实现定义的,这里不再展开说明
  • 标准+扩展有符号整数类型统称有符号整数类型(Signed integer type),标准+扩展无符号整数类型统称无符号整数类型(Unsigned integer type)
  • char+有/无符号符号类型+枚举类型统称整数类型(Integer type)。
  • char+signed char+unsigned char统称字符类型(Character type)。
  • 浮点类型/实数浮点类型(Floating type / Real floating type):floatdoublelong double

需要注意的地方:

  1. 虽然被称为字符类型,但char不仅仅能用来表示字符,它也可以和其他整数类型一样用来表示整数。

  2. char可能是有符号,也可能是无符号,这由实现决定。但无论实现选择char是有符号,它和signed char依然是不同的类型,反之亦然。

  3. 对于short intintlong intlong long int,类型指定符中的signedint可以省略,例如:int = signed int = signedunsigned int = unsigned,short = signed short = short int,等等。而且顺序可以任意打乱,比如说unsigned long long int = long int long unsigned

  4. charunsigned charsigned char的大小保证为1字节(严谨地说C语言中的“字节”不一定是8位的,不过一般也见不到不是8位的实现……)。其他类型大小由实现定义,满足 char <= short <= int <= long <= long long


    常量(Constant)和字面量(Literal)

C语言有整数常量浮点常量枚举常量字符常量,以及字符串字面量复合字面量C99)。

整数常量和浮点常量

1
2
42 // 整数常量,类型为int
2.33 // 浮点常量,类型为double

需要注意的是整数和浮点常量不包含其左侧的正负号。

举例来说的话,假设intlong所能表示的最大值为2^31-1,long long所能表示的最大值为2^63-1,那么:

1
2
3
4
2147483647 // 类型为 int
2147483648 // 类型为 long long
0x7FFFFFFF // 类型为 int
0x80000000 // 类型为 unsigned int

浮点常量的类型就简单多了,无后缀的情况为double,后缀为fF则为float,后缀为lL则为long double

枚举常量

1
2
enum RGB {R, G, B};
R // 枚举常量,类型为int

枚举常量的类型是 int,而非 enum RGB。

字符常量

1
2
3
4
5
'X' // 字符常量,类型为int
'XY' // 多字符常量,类型为int
L'X' // 宽字符常量,类型为wchat_t
u'X' // 16位宽字符常量,类型为char16_t(C11)
U'X' // 32位宽字符常量,类型为char32_t(C11)

不加前缀的字符常量的类型是 int,而非 char。

字符串字面量和复合字面量

1
2
3
4
5
6
7
8
"Test" // 字符串字面量,类型为char[5]
L"Test" // 宽字符串字面量,类型为wchat_t[5]
u8"Test" // UTF-8字符串字面量,类型为char[5](C11)
u"Test" // 16位宽字符串字面量,类型为char16_t[5](C11)
U"Test" // 32位宽字符串字面量,类型为char32_t[5](C11)

struct X { int a, b, c; };
(struct X){1, 2, 3} // 复合字面量,类型为struct X

虽然字符串字面量的类型中没有const,但它实际上是不能修改的(导致UB);但类型中没有const的复合字面量是可以修改的。