2. 值、对象、类型与声明
程序执行时操作的是对象中的值,源代码则通过类型、声明和标识符描述怎样解释与访问这些对象。本章介绍对象、值、类型和标识符这几个基本概念,暂不讨论跨文件可见性;表达式怎样读取、计算和修改对象在第 3 章介绍。
1. 本章内容
2. 习题
#10204
⚡2⏳2
阅读下面的程序,先写出输出,再回答问题。
c
#include <stdbool.h>
#include <stdio.h>
int main(void) {
int a = 10;
int b = a;
bool ready = 0.5;
char letter = 'A' + 2;
a = 15;
b = b + 1;
printf("%d %d %d %c\n", a, b, ready, letter);
printf("%d %d\n", (int)sizeof letter, (int)sizeof 'A');
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
b = a之后又修改a,为什么b的值不受影响?bool ready = 0.5;为什么输出1,而不是0或0.5?sizeof letter与sizeof 'A'为什么不同?后者的值等于什么?
验收:第一行输出必须是 15 11 1 C;第二行第一个数是 1,第二个数等于本机的 sizeof(int)(常见实现为 4)。先写答案再编译核对,对不上的地方要能说出原因。
#10205
⚡3⏳3
写一个程序,打印本机各整数类型的大小、位数和取值范围,并用 <limits.h> 的宏逐项核对。
要求:
- 覆盖
signed char、short、int、long、long long和unsigned char; - 位数用
CHAR_BIT * sizeof(类型)计算,不要手写 8 或 32; - 有符号类型的最小值、最大值分别与
SCHAR_MIN/SCHAR_MAX、SHRT_MIN/SHRT_MAX、INT_MIN/INT_MAX、LONG_MIN/LONG_MAX、LLONG_MIN/LLONG_MAX相等,unsigned char的最大值与UCHAR_MAX相等; - 程序自己比较并打印
match或mismatch,不靠肉眼核对。
本机(MinGW-w64,gcc -std=c17)的输出供对照:
text
type size bits min max
signed char 1 8 -128 127
short 2 16 -32768 32767
int 4 32 -2147483648 2147483647
long 4 32 -2147483648 2147483647
long long 8 64 -9223372036854775808 9223372036854775807
unsigned char 1 8 0 2551
2
3
4
5
6
7
2
3
4
5
6
7
long 在 Windows 上是 4 字节、在 64 位 Linux 上是 8 字节,两种结果都算通过。
#10206
⚡4⏳3
下面的程序有四处缺陷,另有一处命名问题。用 -std=c17 -Wall -Wextra 编译并运行,逐条指出问题、说明依据,再改写为正确版本。
c
#include <stdbool.h>
#include <stdio.h>
int _Engine = 0;
int __count = 0;
int main(void) {
int limit;
int total = limit + 10;
bool flags = 0;
flags = flags + 2;
flags = flags + 4;
int mask = 010;
double rate = 1 / 5;
printf("%d %d %d %.1f %d\n", total, flags, mask, rate, _Engine + __count);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
要求:
- 编译器给出的警告原样抄下来,指出它对应哪一处问题;没有警告的问题也要说明为什么编译器不报。
- 四处问题分别涉及:未初始化的自动对象、用
bool对象保存多个标志、八进制常量的写法与作者本意不符(作者想要十进制 10)、整数常量参与的除法。mask与rate两处程序都能正常跑完,只是结果不是作者想要的,判断依据是后面printf的意图。 - 改写后重新编译,
-Wall -Wextra必须没有任何输出。验收时把limit初始化成 5(取别的值也算对,只要确实初始化了),运行结果应为15 6 10 0.2 0。 - 顺带说明:
_Engine和__count这两个名字为什么不该出现在用户代码里,改写时换成什么名字。
#10207
⚡4⏳3
常量的类型由写法决定。对下面每个记号,先按 2.8 节的规则写出它的类型,再用 sizeof 验证。
text
1
1u
1L
1LL
1.0
1.0f
'A'
"A"
2147483648
0x800000001
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
要求:
- 写一个程序打印每个记号的
sizeof;"A"按数组处理,要写出它的元素类型和元素个数。 - 解释
2147483648与0x80000000的数值相同、类型却不同,原因在十进制常量与十六进制常量的推导规则不一样。 - 预测并验证下面两行的输出,说明第二行为什么与第一行不同:
c
printf("%d\n", 3000000000 > -1);
printf("%d\n", 3000000000u > -1);1
2
2
本机(MinGW-w64,long 为 4 字节)上的结果:各记号的 sizeof 依次为 4、4、4、8、8、4、4、2、8、4;两行比较依次输出 1 和 0。在 long 为 8 字节的平台上,1L 的 sizeof 变成 8,其余记号的类型不变。