You are on page 1of 16

第二讲: C 语言回顾

章节概要
• 指针( Pointer )

• 引用( Reference )

• 数组( Array )

• 结构体( Structure )

• 联合体( Union )

2
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int i;
cout << argc << endl;
for(i = 0; i < argc; i++)
cout << argv[i] << endl;
return 0;
}

• 我们和计算机之间的关系:笔友。联系的方式依靠信件
• 计算机遇到信件中不懂的词语,就会去查询自己的资料库
• 查询:使用 CPU 快速搜索
• 资料库:存储于大容量存储器中,由 #include 限定范围
• 计算机需要频繁地在大容量存储器中快速的查找数据。如何做到?

3
大容量数据管理
• 计算机中存储大规模动态数据
o 数据动态删除与插入
• 如何快速在计算机中定位数据
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int i;
cout << argc << endl;
for(i = 0; i < argc; i++)
cout << argv[i] << endl;
return 0;
}

4
指针( Pointer )
• 指针是一个用于存储内存地址的变量。对于 32 位机而言,
被存储地址范围为: 0 ~ 2^32-1 ,即内存地址用 32 比特
表示。

• 注意(普通)变量和指针变量之间的相似性和不同点

• 与指针变量相关“内容”有:
o 类型、标识符(变量名)、数据(地址)
o 可访问“所指向数据” 及其“地址”
o 可改变“所指向数据”

5
指针 示例 1
int i; // 定义整型变量 i
i = 123; // 将 123 赋值给 i
cout << i; // 输出数据(访问数据本身)
cout << &i; // 访问数据的地址

int* p; // 定义 int 指针类型变量 p


p = &i; // 将 i 的地址赋值给 p
cout << i; // 输出 i
cout << p; // 输出 p
cout << &p; // 输出 p 的地址
// 注:最后两行输出结果不同
6
地址访问运算符( * )
• 如果可以获得一个变量的有效地址,那么可以通过地址访问运算符
( * )访问或改变变量的实际内容

• 地址访问运算符的符号是星号 ‘ *’

• 在某些教材中,地址访问运算被翻译为“取值运算”

• 正确理解指针变量(重要)
o 对于指针 p ,正确理解 p 、 *p 、 &p
注:
p :某个变量的地址
*p :某个变量的实际取值
&p : p 的地址
7
指针 示例 2
int i, j;
int* p; // 指针定义,而非取值运算
i = 123;
p = &i;
j = *p; // 将 p ( &i )处的数据赋值给 j ,即 j=123
*p = 456; // 将 p ( &i )处的数据改为 456 ,即
i=456
cout << i; // 输出 i
cout << j; // 输出 j
cout << *p; // 输出 p ( &i )处的数据,即 i

8
指针和取值运算 示例 3
y = *&x; // 等价于 y=x;

四个常见的错误:
1 、忘记给指针变量赋有效值(野指针)。
2 、指针不能指向一个常量,例如“ int *p=&45; ” 不合法。
3 、指针不能指向一个表达式。
4 、指针不能指向寄存器变量,因为变量不在内存( memory )中。

9
指针
• 根据上面所介绍的内容,我们知道,定义指针一般形式如下:
变量类型 * 变量名;

• 例如常见的 char 、 int 、 float 指针类型


char *a, *b, *c;
int *i, *j, *k;
float *x, *y, *z;

• 仅地址能被赋值给以上三种类型变量,且赋值时存在类型检查

10
无类型指针( void* )
• 我们可以通过 void* 定义一个无类型指针 / 泛指针( Generic
pointer ),此类型指针可以存储任何类型的地址。

• 在 ANSI C 中,支持隐式转化。

• 自动类型转化( automatic casting )发生在编译器检查包含无类型指


针的时候。

例如: void *p,*q,*o;

11
引用( Reference )
• 引用类型和指针类型很相似,但不必单独开辟新的内存单元。

• 定义
int a = 1;
int& b = a; // 定义变量 a 的引用,名为
b

• 使用
cout << b << endl; // 输出结果为 1

• 引用类型必须在定义时初始化

• 一个引用类型变量仅能关联一个变量,然而一个指针可以在任何时候关联新的地

12
引用 示例 4
int x = 10;
int* p = &x; // 指针类型变量
int& ref = x; // 引用类型变量
int& m; // 空引用,无意义,被声明为引用却放弃初始化

13
生命周期( Life Cycle )
• 所有存在计算机中的实体单元,都是有生命和生命周期的!
• 实体单元:被分配了内存,用于存储该数据的
• 每一个实体单元都具有明确的生命周期,即其生存的时间
o 开始于实际内存被分配,终结于内存被收回

#include <iostream>
using namespace std;
int main(int argc, char *argv[])
int x = 10; {
int i;
int* p = &x; // 指针类型变量
cout << argc << endl;
int& ref = x; // 引用类型变量 for(i = 0; i < argc; i++)
int& m; // 无实际生命,仅有个名称 cout << argv[i] << endl;
return 0;
}
14
C 语言回顾
• 基于过程的语言 ( Procedural Language )
o 流程化,按照顺序执行的语句
• CPU 负责快速的搜索查找
• 指针负责管理数据与快速定位数据
#include <iostream>
using namespace std;
• 结构体:多元化数据( struct ) int main(int argc, char *argv[])
{
• 数组:大规模数据访问 ( array )
int i;
• 链表:连续数据访问 cout << argc << endl;
for(i = 0; i < argc; i++)
cout << argv[i] << endl;
return 0;
}

15
知识拓展— ANSI C
20 世纪 80 年代, C 语言广泛流行,许多人为其写变种,
各种 C 版本涌出。因为 C 语言没有一个统一的标准,导致
了它的代码无法在各种编译器上实现, C 语言受到了变种松
散的威胁,因此 C 语言必须进行标准化。
1983 年美国国家标准化组织( ANSI )成立了 C 语言
工作小组,开始对 C 进行标准化, 1989 年 12 月 ANSI C
最终被 ANSI 委员会接纳。 1990 年国际标准化组织( ISO)
也接纳了 ANSI C ,并做了一些小的修改,也就形成了 ISO
C 。 1990 年初, ANSI 委员会重新接纳了 ISO C 。
因此 ANSI C (ISO C) 是 C 语言进行标准化后的产物,
现在所有的编译器理论上都应该符合 ANSI C(ISO C) 标准。

16

You might also like