高级指针部分编写完毕。
This commit is contained in:
parent
2f79771c00
commit
03a7c0a9d1
|
@ -178,6 +178,27 @@ void* p1 = p0;
|
|||
|
||||
## 2.8.6 指针与函数
|
||||
|
||||
函数、或者说程序本身在运行时也是要占用内存空间的。因此,可以使用指针,像指向某个变量那样指向这个函数:
|
||||
|
||||
```cpp
|
||||
typedef void (*P_FUN_TYPE)(int a);
|
||||
|
||||
void fun(int a)
|
||||
{
|
||||
printf("%d", a);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int a = 0x10;
|
||||
P_FUN_TYPE pfun = fun;
|
||||
|
||||
pfun(a); // 与直接调用 fun(a) 是一样的.
|
||||
}
|
||||
```
|
||||
|
||||
这样可以指向函数的指针称为函数指针。在一般的程序中,函数指针并不常见。但,如果你编写的程序具有某种框架,例如 linux 内核中的驱动框架,就会大量使用函数指针了。
|
||||
|
||||
## 2.8.7 多级指针
|
||||
|
||||
前面提及指针的实质是变量,因此也有一个内存空间用于保存指针的值,同样也有一个内存地址与之对应。这就是说,我们可以通过一个指向指针的指针去访问另一个指针,这被称为二级指针或多级指针。
|
||||
|
@ -187,21 +208,83 @@ int a=10;
|
|||
int* pa = &a;
|
||||
int** ppa = &pa;
|
||||
|
||||
printf("%d", **ppa);
|
||||
printf("%d\n", **ppa);
|
||||
```
|
||||
|
||||
## 2.8.8 指针参数
|
||||
|
||||
以上所说的全部类型指针都可以作为函数的参数来进行传递。
|
||||
|
||||
```cpp
|
||||
|
||||
void fun(int* arry, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<size; i++)
|
||||
printf("%d\n", arry[i]);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int codeList[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
|
||||
fun(codeList, sizeof(codeList)/sizeof(*codeList));
|
||||
}
|
||||
```
|
||||
|
||||
对于参数的传递,有值传递和引用传递两种。C 语言本质上只支持值传递。但通过指针,可以达到传递引用的效果——这是因为指针本身就是对其他变量的引用。
|
||||
|
||||
## 2.8.9 指针与内存泄漏
|
||||
|
||||
数组访问的溢出
|
||||
没有释放的内存
|
||||
野指针
|
||||
使用指针时,有些事情是需要特别注意的。
|
||||
|
||||
当使用指针来访问数组时,有可能访问的范围超过了数组自身的实际长度,这是非常危险的,并且在任何情况下都应该避免:
|
||||
|
||||
```cpp
|
||||
int arry[6];
|
||||
int* p = arry;
|
||||
|
||||
p += 10;
|
||||
p = 0x55; // 数组方位越界.
|
||||
```
|
||||
|
||||
如果指针没有被初始化,则将其赋值为 NULL,即空指针。另外,在使用完指针后也应该将其赋值为 NULL。这样,在程序中通过对指针值得判断,可以知道这个指针是否有效。无效得指针非常可怕,我们将其称为野指针。
|
||||
|
||||
```cpp
|
||||
typedef void (*P_FUN_TYPE)(int a);
|
||||
|
||||
void fun(int a)
|
||||
{
|
||||
printf("%d", a);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int a = 0x10;
|
||||
P_FUN_TYPE pfun; // pfun 没有被初始化过, 被称作野指针.
|
||||
|
||||
pfun(a); // 调用 pfun(a) 之后程序不知道跑到了哪里去,程序跑飞了.
|
||||
}
|
||||
```
|
||||
|
||||
很多时候,我们使用 malloc() 等函数为指针分配一个空间,但是在使用后我们忘记了释放,然后下次又接着申请了。这使得内存越用越少,很多内存脱离了程序应有得掌控范围,造成内存泄漏。
|
||||
|
||||
```cpp
|
||||
int* p = NULL;
|
||||
int i;
|
||||
|
||||
for(i=0; i<1024; i++)
|
||||
p = malloc(1024);
|
||||
|
||||
p = NULL;
|
||||
// 很快 1M 内存就消失了,并且这块内存无法再被回收。
|
||||
```
|
||||
|
||||
内存泄露他同样是极旗危险得,它不仅造成程序和系统不稳定,也会危害系统安全,泄漏用户隐私数据等。
|
||||
|
||||
## 练习
|
||||
|
||||
1、Program 2-8-4-1 中同样有编译警告,你该如何去除这些警告?
|
||||
|
||||
函数指针
|
||||
指针数组
|
||||
数组名
|
||||
2、如果有多个不同得设备,他们的读写方法不同,但是调用接口的形式是一致的,我们的主程序要读写所有的设备,该怎样实现最高效,能否将这些设备组织在一个数组中?
|
||||
|
|
Loading…
Reference in New Issue