内存的编号:
一个字节(8个位)一个字节编号(即 8个1 或者 8个0)
一个字节一个编号:编号即地址。
地址(内存单元的编号)
指针:
指针的重要性
1、 表示一些复杂的数据结构
2、快速的传输数据
3、使函数返回一个以上的值
4、能够直接访问硬件
5、能够方便的处理字符串
6、是理解面向对象语言中引用的基础。
总结:指针是c语言的灵魂
#include <stdio.h>
int main(void)
{
int * p;
//p是指针变量(地址变量)的名字,int * 表示p编量存放的int类型变量的地址;
// int * p 不应该定义了一个名字叫做 *p的变量;
// int * p 应该这样理解: p是变量名,p变量的数据类型的 int * 类型;
// 所谓int * 类型 实际就是存放 int变量地址的类型。
int i;
p = &i;
/*
1、p保存了i的地址,因此p指向i,
2、p不是i,i也不是p,更准确的说:修改p的值不影响i;
修改i也不影响p;
3、如果一个指针变量指向了某个普通变量,则*指针变量
就完全等同于 普通变量
例子:
如果p是个指针变量,并且p存放了普通变量i的地址
则p指向了普通变量i。
*p 就完全等同于 i;
即 在使用出现 *p的地方都可以替换成 i;
在所有出现 i 的地方都可以替换成 *p;
*/
return 0;
}
1、指针就是地址,地址就是指针;
2、地址就是内存单元的编号;
3、指针变量是存放地址的变量;
4、指针和指针变量的两个不同的概念;
5、但是要注意:通常我们叙述时会把指针变量简称为指针;
实际它们含义并不一样;
6、指针的本质就是一个操作受限的非负整数(只能进行减运算)。
指针的基本类型:
1、
*号的用法:
1、乘法;
2、定义指针变量
//定义了一个名字叫p的变量,int * 表示只能存放int变量的地址;
3、指针运算符
该运算符放在已经定义好的指针变量的前面;
如果p是一个已经定义好的指针变量;
则*p表示 以p的内容为地址的变量;
指针和数组:
指针和一维数组
一维数组名是个 指针 常量
它存放的是一维数组的地址;
下标和指针的关系
如果p是个指针变量,则
p[i]永远等价于*(p+i)
确定一个一维数组需要几个参数
如果一个函数要处理一个一维数组,则需要接收该数组的那些信息。
需要两个参数:
数组第一个元素的地址,
数组的长度;
指针变量的运算
指针变量不能相加,也不能相乘,相除;
(如果两个指针变量指向的是同一块连续空间的不同的存储单元,
这两个指针变量才能相减。)
一个指针变量到底占几个字节;
知识:
sizeof(数据类型)
功能:返回值就是该数据类型所占的字节数;
例子:sizeof (int) = 4; sizeof(char)= 1;
sizeof(double) = 8;
sizeof(变量名)
功能:返回值是该变量所占的字节数;
假设p指向char类型变量(1个字节)
假设q指向int类型变量(4个字节)
假设r指向double类型变量(8个字节)
p q r 本身所占的字节数是否一样
一样,本身所占字节数为4;(32个状态,即32跟线)
总结:一个指针变量,无论它指向的变量占几个字节;
该指针变量 本身 只占四个字节
一个变量的地址使用该变量 首字节的地址 来表示;
内存中一个字节(8bit)对应一个编号
指针和二维数组
printf("%#x\n",&a[0]); //a[0]地址的输出;
如何通过被调函数改变主调函数的值:
1、实参必须为该普通变量的值。
2、形参必须为指针变量。
3、在被调函数中通过
*形参名 = ....
的方式就可以修改主调函数相关变量的值。
专题: (非常重要)
动态内存控制:
传统数组的缺点:
1、数组长度必须事先制定,并且只能是常整数;不能说变量;
int a[5]; //ok
int len = 5; int a[len]; //error
2、传统形式定义的数组,该数组的内存程序员无法手动释放。
数组一旦定义,系统就会为该数字分配存储空间就会一直存在。
除非数组所在地函数运行结束。
在一个函数运行期间,系统为该函数中数组分配的
内存空间会一直存在,直到该函数运行完毕时,
数组的空间才会被系统释放。
3、数组的长度一旦定义,其长度就不能在更改。
数组的长度不能在函数运行的工程中动态的扩充或缩小。
4、传统方式定义的数组不能跨函数使用。
A函数定义的数组,在A函数运行期间可以被其他函数使用,
但A函数运行完毕之后,A函数中的数组将无法被其他函数使用。
原因是: 调用函数运行完毕,数组空间被释放了。。。
为什么需要动态分配内存:
动态数组很好的解决了传统数组的这4个缺陷。
传统数组也叫静态数组。
动态内存分配举例___动态数组的构造(难点)
静态内存和动态内存的比较
1、静态内存是由系统自动分配,由系统自动释放;
2、静态内存是在栈分配的,
3、动态内存是有程序员手动分配, 手动释放的;
4、动态内存是在堆分配的,
跨函数使用内存的问题:
地址:内存单元的编号;