.
1. 地址算数运算示例
指针算数运算 : int *p, array[5]; p = array; p 指向一个 int 数组元素, p + i 的地址时数组中第 i 个元素的地址, 即 p + i 指向 第 i 个元素;
存储分配示例函数 :
-- char *alloc(int n) 函数 : 传入分配的字符个数, 返回连续字符存储单元指针, 这个指针可以存储 n 个字符元素;
-- int afree(char *p) 函数 : 释放分配的内存空间;
-- 缺陷 : 分配内存的时候, 有一个偏移量, 偏移量的大小代表已经分配了多少内存, 释放内存必须按照分配内存的顺序释放, 否则偏移量就会乱;
-- 内存分配原理 : 设置一个大数组, 内存分配就分配这个数组的中的空间, alloc 和 afree 函数操作的是指针, 不是数组, 因此这个数组可以隐藏, 将数组定义为static 类型, 那么在其它文件中, 不能访问该数组, 设置一个偏移量, 当分配 n 个元素, 偏移量就加上 n, 当偏移量 等于 数组大小, 说明内存全部分配完毕;
-- 偏移量设计 : 设置一个偏移量, 偏移量始终指向大数组的下一个空闲的元素地址, 当分配内存的时候, 通过计算 数组首地址 + 数组长度 - 偏移量 >= 分配大小 , 成立的话就可以分配内存, 分配内存就是将偏移量 加上 分配大小; 释放内存的时候, 就将偏移量 指向 释放内存的指针的首地址, 因此 要保持后进先出的次序;
代码 :
/*************************************************************************
> File Name: alloc_afree.c
> Author: octopus
> Mail: octopus_work.163.com
> Created Time: 2014年03月17日 星期一 19时34分08秒
************************************************************************/
#include
//用于内存分配载体的大数组大小
#define ALLOCSIZE 1000
/*
* 该数组就是用于内存分配的主体,
* 设置为static , 意味着只能在本文件中访问, 在其它文件中不能访问
*/
static char alloc_buf[ALLOCSIZE];
/*
* 将alloc_buf 数组的首地址赋值给allocp字符指针
* 对allocp 进行算数运算, 每次加减都是 char * 运算数
* allocp的值就可以代表所分配内存的首地址
*/
static char *allocp = alloc_buf;
/*
* 分配n个char类型数组的内存,
* 如果分配成功, 返回分配的内存的指针,
* 如果分配失败, 返回0
*/
char *alloc(int n)
{
//如果大数组剩余的空间可以分配, 那么就进行分配
if(alloc_buf + ALLOCSIZE - allocp >= n)
{
//分配空间, allocp 指向下一个空间的内存首地址
allocp += n;
//返回分配的空间首地址
return allocp - n;
}else //如果数组剩余空间不足, 返回0
{
return 0;
}
}
/*
* 释放分配的内存
* 释放内存就是将allocp 指针地址指向 要释放的内存指针首地址
*/
void afree(char *p)
{
//释放内存的前提是 内存必须是大于数组首地址, 小于数组尾地址
if(p >= alloc_buf && p < alloc_buf + ALLOCSIZE)
{
allocp = p;
printf(allocp = %p
, allocp);
}
}
int main(int argc, char **argv)
{
char *p1;
char *p2;
char *p3;
char *p4;
//打印数组首地址
printf(alloc_buf = %p
, alloc_buf);
//分配300个字符内存
p1 = alloc(300);
printf(char *p1 = alloc(300), p1 = %p
, p1);
p2 = alloc(300);
printf(char *p2 = alloc(300), p2 = %p
, p2);
p3 = alloc(300);
printf(char *p3 = alloc(300), p3 = %p
, p3);
//上面已经分配了900了, 在分配就溢出了, 这里alloc()函数返回0
p4 = alloc(300);
printf(char *p4 = alloc(300), p4 = %p
, p4);
afree(p4);
afree(p3);
afree(p2);
afree(p1);
}
执行结果 :
octopus@octopus-Vostro-270s:~/code/c/pointer$ gcc alloc_afree.c
octopus@octopus-Vostro-270s:~/code/c/pointer$ ./a.out
alloc_buf = 0x804a060
char *p1 = alloc(300), p1 = 0x804a060
char *p2 = alloc(300), p2 = 0x804a18c
char *p3 = alloc(300), p3 = 0x804a2b8
char *p4 = alloc(300), p4 = (nil)
allocp = 0x804a2b8
allocp = 0x804a18c
allocp = 0x804a060
函数执行示例图 :
-- alloc()函数示例图 :

-- afree()函数示例图 :

指针初始化 : static char *allocp = alloc_buf, 将char数组的首地址赋值给char类型指针;
-- 初始化内容 : 0 或者 地址;
-- 地址限定 : 对指针初始化的地址, 该地址存储的数据的类型必须是该指针类型;
内存可用判断 : alloc_buf + ALLOCSIZE - allocp >= n;
-- 意义 : alloc_buf 是数组首地址, ALLOCSIZE 是数组大小, allocp是可用内存偏移量, alloc_buf + ALLOCSIZE -allocp 结果是可用的内存量, 如果可用内存大于n, 则可以赋值;
-- 如果内存不足 : 内存不足, 将0作为地址返回, C语言中设定 0 不是有效的数据地址, 0地址的数据为NULL, 返回0表示发生了异常事件;
指针整数转换特例 : 指针 和 整数 不能相互转换;
-- 通常情况 : 指针 和 整型 之间不能相互转换, 0 除外;
-- 特例 : 常量 0 可以赋值给指针, 指针 可以和 常量 0 进行比较, 这里注意是常量;
-- 0的特殊性 : NULL 可以代替 常量0, 常量0 是一个特殊值;
指针运算 :
-- 比较运算 : 两个指针都指向同一个数组中的元素, 那么两个指针之间的比较是有意义的, 指向两个不同数组元素的指针之间比较无意义;
-- 加减运算 : 指向数组元素的指针, 进行加减运算, 地址的计算按照 运算数 * 指针指向元素的大小 进行计算;
计算字符串长度示例 :
-- 代码 :
/*************************************************************************
> File Name: strlen_pointer.c
> Author: octopus
> Mail: octopus_work.163.com
> Created Time: 2014年03月17日 星期一 21时38分52秒
************************************************************************/
#include
//计算字符串长度
int strlen(char *s)
{
//指针 p 记录首地址
char *p = s;
//循环获取字符串最后的字符首地址
while(*p != '')
p++;
//字符串占用的内存地址个数
return p - s;
}
int main(int argc, char **argv)
{
char *c = fuck you!!;
printf(length = %d
, strlen(c));
return 0;
}
--
执行效果 :
octopus@octopus-Vostro-270s:~/code/c/pointer$ gcc strlen_pointer.c
octopus@octopus-V