指针的基本概念:
int * p;
p是一个变量名字,int * 表示该p变量只能存储int类型变量的地址
当p指向变量i,p变量就存放的是i的地址,*p即是i
指针就是地址,地址就是指针
指针变量是存放内存单元地址的变量
如果一个指针变量指向一个普通变量,那么 * 指针变量就等同于普通变量,*p就完全等同于i
用指针可以使函数返回(return)不止一个值
能直接访问硬件(因为指针就是地址)
指针->地址->内存单元的编号
cpu控制内存条的三根线:
用指针写一个swap函数:
#include <iostream>
using namespace std;
void swap(int * p, int * q) //int * p, p存放int类型的地址
{
int t;
t = *p;
*p = *q;
*q = t;
return;
}
int main()
{
int a = 3;
int b = 5;
//?swap(a, b) 错误,int类型和int*类型不一致
swap(&a, &b);
printf("a = %d, b = %d", a, b);
}
使函数返回一个以上的值:
#include <iostream>
using namespace std;
void g(int * p, int * q) //int * p, p存放int类型的地址
{
*p = 1;
*q = 2;
}
int main()
{
int a = 3;
int b = 5;
g(&a, &b);
printf("a = %d, b = %d", a, b);
}
指针和数组:
int a[5];
一维数组名是一个指针常量
存放的是一维数组第一个元素的地址
#include <iostream>
using namespace std;
int main()
{
int a[5];
int b[5];
printf("%#X\n", &a[0]);
printf("%#X\n", &a);
return 0;
}
用函数输出数组内容:
确定一个一维数组需要几个参数(如果一个函数要处理一个数组,需要接收哪些信息)
1.数组首地址
2.数组的长度
#include <iostream>
using namespace std;
void f(int * pArr, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d ", *pArr++);
}
}
int main()
{
int a[5] = {1, 2, 3 ,4 ,5};
int b[5] = {-1, -2, -3 , -4 , -5 };
f(a, 5);
f(b, 5);
return 0;
}
在f函数中用
pArr[3] = 88
可以对a[3]进行修改
pArr[3]就等价于*(pArr+3)
而a[3]就等价于*(a+3)
指针变量所占字节:
sizeof()
p指向char类型(1个字节)
q指向int类型(4个字节)
r指向double类型(8个字节)
p q r所占字节数是否一样?
是一样 为4个字节
一个变量的地址用第一个字节的地址表示
为什么是四个字节?
从cpu到内存有32根线,一个字节就是八比特,32个状态用4个字节表示
动态分配内存:
传统数组的弊端:
传统数组长度必须实现确定,且只能是常整数(不能是变量)
该数组内存程序员无法手动释放
malloc:
memory(内存)allocate(分配)
int * p = (int *)malloc(4)
malloc函数只能返回第一个字节的地址
分配了八个字节,p指针占四个字节,p指向的内存也占四个字节
p本身所占内存是静态分配的,p所指向的内容是动态分配的