Chap 9:指针
来源:互联网 发布:linux安装exe软件 编辑:程序博客网 时间:2024/06/05 04:27
9.1 指针概念
预备知识
1 内存
总线:地址线(64M=26根) 数据线(32根) 控制线(读写)
地址:最小单位(0地址-0字节,1地址-1字节) 对齐(指令是按4字节对齐的)
2 指令
访存指令: 可以读写内存,用2个寄存器,一个存地址,一个放数据
LDR r0, [r1]// mem(r1) -> data(r0)STR r0, [r1]// data(r0) -> mem(r1)
怎么区分内存里面的数据和指令?
PC 程序计数器,一般初值为0,指向第一条指令除非碰到跳转指令,否则通常情况下,pc = pc + 4
3 变量
变量的本质是什么? 变量是C语言出现之后才有的
2个属性:变量名 int a = 100; 变量值 a + 2;
变量的本质是:在C语言中,由C编译器分配的,表示内存地址和存储单元内容的一种联系。
4 指针变量
指针的本质是什么? 指针也是一种变量,但这个变量值它就是内存地址。
0xbfxxxxxx 函数栈内,局部变量
0x8048xxx 数据段,全局变量
9.2 指针用法
1 指针变量定义:
int * p;
2 指针变量赋值:
p = &a;// goodp = 0x8048xxx;// no error, not good.
补充: int * p = &a; 应该看待为 int* p; 同时 p = &a; 而不是 p = &a;
3 指针变量使用:
*p = 200;// 赋值printf("%d", *p);// 读内容 p--;// 指针调整
4 指针变量类型:
char * p;short * p;int * p;指针变量的类型,决定了用 *p 去访问内存时候的读取的字节数
5 易混淆的错误
1) &a 的用法
&a 是一个常量(由编译器决定),代表内存地址&a 是一个32位整型,与a是什么类型无关&a = 100; 试图修改a的地址,这样的用法是错误的
2) p 的用法
int * p;*p = 1;// wrong!p = 1;// no error给指针本身赋值p=1是允许,但如果用指针取内容 *p=1 这是有风险的,会出段错误。
6 指针的重要用法-传参
用于获取用户输入
int a;scanf("%d", &a);int * p = &a;scanf("%d", p);
用于交换 swap 函数
void swap(int * a, int * b);// 可以用于修改上一级主调函数内部的变量的值
也可以通过传指针来获取多于1个以上的返回值
void decompose(double x, long * int_part, double * frac_part);
课堂练习: 请使用 char * 指针,对一个整型数 a = 0x12345678 修改为大端存储 提示: void swap(char * p1, char * p2);
7 指针的重要用法-const保护
int main(int argc, const char * argv[]);int printf(const char * format, ...);int scanf(const char * format, ...);char * strcpy(char * dst, const char * src);const int * p;// const 修饰 *p*p = 100;// error*(p+1) = 100;// next pos is error tooa = *p;// okp++;// ok
对比学习 const 的另一种用法
int * const p;// const 修饰 p*p = 100;// oka = *p;// okp++;// error
8 指针的重要用法-用作返回值
用传入的指针作为函数返回的指针,这是允许的。
重要结论: 如果是函数内部局部变量的地址作为指针返回,这是有风险的。(编译没错,但不好)
9.3 指针和数组
1 指针的算术运算
1) 加一个整数 p+1 (地址的增加值取决于指针的类型,整型指针则加4)2) 减一个整数 p-1(地址的减少值取决于指针的类型,整型指针则减4)3) 两个指针相减p1-p2(结果是两个指针之间的元素个数,而不是字节数)只有相同类型的指针才能作减法,不同类型不能相减,编译器会报error4) 自增加 p++, ++p5) 自减少 p--, --p6) 指针的比较(p1 > p2)
2 特殊类型指针 void * p
void * p = &a;// okp = 100;// oka = *p;// error*p = b;// errorp+1 (整数加1)// okp++/++p(加1)// okvoid * malloc(size_t);
3 指针名和数组名
int a[10];int * p = a;有何异同?a[0]vsp[0]=> 相同的*pvs *a=> 相同的*(p+1)vs *(a+1)=> 相同的p+1vsa+1=> 相同的p++vs a++=> 不同的(数组名是一个常量,不能修改)
4 指针和二维数组
int a[5][6];int * p = &a[0][0];int * p = a;int * p = a[0];int * p = a[2];
课堂作业: 请用指针实现对一个数组的调整,要求奇数在左边,偶数在右边。 要求: 尽可能不占用额外的存储空间。
编程方法
最重要的就是分解(设计好的函数),更重要的,在于设计程序时,从何种角度考虑解法?
判定标准:1) 逻辑简单 (嵌套少一些)能用1个while,就不用2个能不用else,就不用while, if, for 之间的递进逻辑少代码行数来作为参考2) 学会设计函数原则上,能够复用的函数是好的设计,能多次复用最好函数的功能最好少一些,一个函数只完成一个单一功能函数内部除了调试语句打印外,最好不打印3) 数据驱动编程《Unix 编程艺术》 -> Data Drive精心考虑所谓算法处理过程中要发生变化的数据是什么,以及何种条件下变化?
5 动态内存分配 allocate
堆heap 和 栈stack 的概念
&a = 0xbf9cb86c 栈空间 3G 向下p = 0x8129008 堆空间 向上&b = 0x804a018 数据段(全局变量)跟着代码段main = 0x8048414 代码段最小
常用函数
void * malloc(size_t size);void free(void * ptr);void * calloc(size_t nmemb, size_t size);void realloc(void * ptr, size_t size);void * alloca(size_t size);
- Chap 9:指针
- CHAP
- {Effective Java} Chap 9 Exceptions
- chap 9 错误处理和debugging
- Chap 9 学习笔记-静态类成员和类关系
- chap 1
- Chap 07: 多线程
- ppp(pap&chap) concept
- chap协议原理
- CHAP协议解释
- Chap 10:字符串
- 编程珠玑 Chap 2
- Chap 5 习题解答
- learning bash-chap 01
- RUDIUS协议-CHAP加密
- FreeRadius: MS-CHAP v2
- Chap 1--Introduction
- PAP与CHAP对比
- 如何在一台机子上启动两个TOMCAT
- hduoj2063:过山车
- 函数调用方式
- 位操作/指针和数组/字符串
- printf函数实现
- Chap 9:指针
- Android中实现Gallery 点击放大
- Chap 10:字符串
- C语言复习串讲课堂笔记
- ASCII表
- sizeof用法
- 再见腾讯,创业我来了!!!
- MySQL的一些基本操作
- 每天都应该问自己的5个问题