<C> 指针

引入:

二进制中的三位 对应 八进制中的一位

二进制中的四位 对应 十六进制中的一位

例:001 010 011(2)→123(8)→0x53(53)

注:在位数不够的时候 前面补零去看

一.对一个变量我们可以进行哪些操作

1.写操作:a = 10;

2.读操作:用printf输出一个数的值

3.取地址操作:&a; 

①内存→一个格子一个字节 例如:int a; 就是向系统申请了四个字节

一个格子就像一个房间 每个房间都有不同的编号 这个编号 就可以叫做内存的地址

②表示方法:取地址符 + 变量名称

如若想查看一个一个变量的地址 可以打为 printf("%p ",&a); 来查看a的地址 返回的是首地址

③在32位中 地址是由8个16进制的数组成的 (00000000~FFFFFFFF)

注:每次在查看地址的时候 地址是变的 不是固定的

因为程序执行结束以后地址就会被收回 如果要再次执行就要重新分配空间

地址的名字是不再占用内存空间的

④地址偏移:

int型 4个字节 输出&a 和&a+1 结果差4

char 1个字节 输出&b 和&b+1 结果差1

结论:看指针所能操作的内存大小 看类型 与右边无关 看左边

间接引用 *:指的是对内存空间进行操作

用法:* + 地址

二.指针

1.定义:本质是用来存储地址的变量

用法:变量类型 + * + 名(变量类型是需要存储地址的变量类型

例如:

1 int* p = &a;
2 //p中存的是a的地址

注:p→&a 即*p = *&a = a的值 p中放的是a的地址 *p是a的值 指向空间的内容

2.sizeof():

sizeof不是一个函数 是一个操作符 是求变量或者类型的大小的(即占多少个字节)

例如:

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a = 10;
 5     char b = 'a';
 6     int* p = &a;
 7     char* pp = &b;
 8     printf("%d
",sizeof(p));
 9     printf("%d
",sizeof(pp));
10 }

上面这段程序在32位电脑中 运行的结果是4 4 在64位电脑中 结果应该是8 8

那么这就说明了:指针的大小与指向变量的类型是无关的

3.如何判断一个变量的类型呢?

去掉变量名 剩下的就是类型 

4.如何判断一个指针所指向的类型?

去掉变量名 去掉一个* 所剩下的就是指针所指向的类型

5.多个指针可以指向同一空间(变量)因为他们的值是一样的

例题:

1 #include<stdio.h>
2 int main()
3 {
4     int a;
5     int* p1 = &a;
6     int* p2 = &a;
7     *p1 = 100;
8     printf("%d
",*p2);
9 }

 6.大端存储和小端存储:

大端存储通常在网络设备中 与小端相反 小端存储一般用于个人电脑 是低地址存在低字节中

字节序是从左到右的 从高到低

例题:int a = 0; char* p = &a;如何能让printf("%d ",a)输出999999?

999999的二进制为 00000000 00001111 01000010 00111111(0 15 66 63)

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a = 0;
 5     char* p = &a;
 6     *p = 63;
 7     p = p + 1;
 8     *p = 66;
 9     p = p + 1;
10     *p = 15;
11     printf("%d
",a);
12 }

注:指针的大小与右边是无关的 与左边的类型有关

以下两种解决方式也都可以 在数组的地方 还可以有第四种解决方式

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a = 0;
 5     char* p = &a;
 6     *p++ = 63;
 7     *p++ = 66;
 8     *p++ = 15;
 9     printf("%d
",a);
10 }
 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a = 0;
 5     char* p = &a;
 6     *p = 63;
 7     *++p = 66;
 8     *++p = 15;
 9     printf("%d
",a);
10 }

三.运算符优先级

这里放几道例题:a = 0; b = 1;

1.a = b++; //输出结果为 a = 1; b = 2;

2.a = ++b; //输出结果为 a = 2; b = 2;

3.a = ++b + ++b; //输出结果为a = 6; b = 3;(两边的b都变成了3)

4.a = b++ + b++; //输出结果为a = 2; b = 3;(这里的b是到下一行才变的)

5.

1 int n = 21;
2 printf("%d %d
",n,n++);

输出结果为:22 21

这里就要提到一个叫函数栈的东西 它是符合栈的存储形式的

n先进栈 n++后进栈 先计算n++ 但此时n已经变成22 所以n输出为22

1 int n = 21;
2 printf("%d %d
",--n,--n);

输出结果为:19 19

.野指针

如果申请了一个指针 暂时不知道应该存谁的地址 那么就让它 = NULL

注:永远都不要操作不属于你的程序的内存空间

五.二级指针

这里就简单粗暴的放一道例题了解一下:

int a = 1; int b = 2; int* p = &a; int** pp = &p; 怎样才能使pp通过printf("%d ",*p)输出b的值?

#include<stdio.h>
int main()
{
    int a = 1;
    int b = 2;
    int* p = &a;
    int** pp = &p;
    *pp = &b;
    printf("%d
",*p);
}

分析:*p = a

* pp = p = &a

** pp = a

原文地址:https://www.cnblogs.com/Aaaaaalei0612/p/8684482.html