地址就像是变量的身份证

运算符 &

对变量进行运算, 返回这个变量的地址

  • 本地变量定义在栈中是自上而下的
  • 数组a,&a,&a[0]地址相同, 相邻地址差一个字节数, 下标大的地址大

输出时:

int i = 0;
printf("0x%x\n", &i);	// 会有汪咛, 因为c出地址有更好的
printf("%p\n", &i);		// %p
int i = 0;
int p;
p = (int)&i				// 不加int有汪咛
printf("0x%x\n", p);	// 没有汪咛了
printf("%p\n", &i);		// %p

所以地址数据类型有别于整形, 又有关于整形 (以上结果在32位或64位结果会不同)

指针类型变量

就是专门去保存那个形如&i的变量 当我们说 p指向 i其实是说, p这个变量里面存放的是 i的地址


int* p,q;
int *p,q;

两种写法没区别, 但那时p是指针了, q还是一个int
* 给的是p, 不是int
事后金: 这里 p是一个指针变量, 访问指向 p的变量的方法是 *p 好, 也就是说, p是指针, *p是变量, 每个类型数据都有其对应地址, 所以这个定义指针的方式是多么巧妙

至于我指向的到底是数组呢还是单个元素呢? 绝对是单个元素的地址 因为我指向一个地方, 这个地方只有一个类型, 如果它恰好是数组, 有一块连续的内存空间 那我可以通过地址的运算得到数组的其他值, 看起来就像”指向了数组”

作为函数参数的指针

void f(int *p); 被调用时得到某个变量的地址 int i=0; f(&i)

  • 在函数里可以通过这个指针 访问 外面的这个i 普通的传值只传值, 之间没有任何关系

这里没什么新奇的, 变量是指针变量, 同样传入的是值, 只不过这个值是地址而已 牛逼的是地址


什么时候会用到呢?

  • 当我们需要返回多个值的时候, 就可以传入地址, 传入的*地址就是”接收”返回值的变量 传进去的是参数, 作用是把结果带出来
  • 函数需要返回运行状态(0,-1之类的), 这时候函数的返回结果怎么办? 利用地址 其实思路是差不多的

访问地址上的变量

*是一个单目运算符

  • *[地址] 可以完整的作为变量, 当左值当右值
  • 可以给指针用, 也可以给数组用

int *p;
int k=12;
*p = 2;

有问题吗? ——太有问题了, 定义了指针变量, 却没有传入地址, 那么在写入这个地址的变量的时候, 要是不凑巧就崩溃了

指针运算

+1是+一个单元, 而单元==sizeof(类型) 也就是字节

  • 给指针 +,-,+=,-= 一个数
  • ++,—
  • 两个指针相减
    • 返回整数, 是地址差/sizeof(类型) 也就是 “间距 ”
  • 可以比较指针的大小 (就是地址数值的大小)

  • 实际上指针运算的意义在于内存上的一块连续区域, 也就是数组 不是连续区域的话, 意义不是很大 不确定, 反正我实际写的时候出了问题


指针与数组

数组变量是const的指针

int b[]int * const b

int a[5] = {0};
int vir=2;
a[0]=1;
 
int *b=a;
cout<<b[0]<<endl;		// 1
cout<<(&vir)[0];		// 2
  • 数组变量名是地址常量, 所以赋给指针变量可以实现数组的浅复制 我好像知道为什么会有浅复制了
  • a==&a[0]
  • []运算符可以对数组(名常量)做, 也可以对指针做 说白了就是对地址做
  • *(b+n) > a[n]

数组中的元素在内存中是连续依次排列的

数组的特点

void b(int* c) {
    c++;
    *c = 1;
}
 
int main(){
    int a[5] = {0};
	b(a);
	cout<<a[1];		// 1
	
    return 0;
}

这也看到了以数组做参数可以用起码两种方式

  • void f(int a[])
  • void f(int *a)


指针与const

常量指针 const int *pint const *p

  • 不能改p指向的变量的值, (当然啦, 这个变量本身可以改的)
  • 但可以改p所指向的地址

指针常量 int * const p

  • 不能改p指向的地址
  • 但可以改p所指向的变量的值

动态内存分配

malloc 和 free



题外话

0地址 NULL

0地址通常是不能随便碰的地址 要使用0地址最好用NULL, 因为有的编译器不喜欢用0

指针的类型转换

void* 表示不知道指向什么的指针 往往用在底层开发中

  • 计算时与 char* 相同, 但不相通
  • 用于转换类型: int *p=&i; void *q=(void*)p;
    • 这没有改变p所指的变量类型, 而是让后人用不同的眼光通过p看它指的变量
    • 我不再当你是int啦, 我认为你就是个void