内存和地址
地址在C语言中又叫做指针
内存单元的编号=地址=指针
该如何理解编址?
计算机内有很多的硬件单元,而硬件单元是要相互协调工作的
CPU和内存之间也有大量数据交互,用“线'连起来(地址总线,数据总线,控制总线)
32位机器上有32根地址总线,每根线表示1或0,每根线可以表示2种状态,32根可以表示2^32种情况,每一个就代表一个地址.
变量创建的实质是:
向内存中申请空间。
#include<stdio.h>
int main()
{
int a=10;//int占用4个字节
printf("%p",&a);//取得其实是较小字节的地址
}
指针变量和解引用操作符
指针变量:
我们用& 取到一个地址,把它存放在指针变量里。
#include<stdio.h>
int main()
{
int a = 10;
int* pa = &a;
printf("%p ",pa);
return 0;
}
运行结果
pa就是一个变量,是用来存放地址的变量 ,即 指针变量。
存放在指针中的变量都是地址。
如何拆解指针变量类型?
pa的类型是int*,* 说明pa为指针变量,int 说明pa指向的变量是int类型的。
解引用操作符(*)
#include<stdio.h>
int main()
{
int a = 10;
int* pa = &a;
printf("%p ",pa);
printf("%d ",*pa);
return 0;
}
指针变量的大小
指针变量为了存放地址,地址存放需要多大空间,指针变量就需要多大空间
大小只跟环境有关
32位 4个字节,64位 8个字节
指针变量类型的意义
解引用
指针变量类型决定了对指针引用时有多大权限(一次操作几个字节)
#include<stdio.h>
int main()
{
int m = 0x11223344;
char* pi = (char*) & m;
*pi = 0;
return 0;
}
#include<stdio.h>
int main()
{
int m = 0x11223344;
int* pi =& m;
*pi = 0;
return 0;
}
指针+-整数
指针类型决定了指针向前或向后走一步有多大。
#include<stdio.h>
int main()
{
int n = 10;
int* p = &n;
char* pi = (char*) & n;
printf("%p\n", &n);
printf("%p\n", p);
printf("%p\n", p + 1);
printf("%p\n", pi);
printf("%p\n", pi + 1);
}
由图可知,当类型为char*时,地址加1个字节;类型为int*时,加4个字节。
void*指针
局限性:void*类型的指针不能直接进行指针+-整数和解引用的运算
作用:可以使用在函数参数的部分,用来接收不同类型数据的地址,可以实现泛型编程,使得一个函数来处理多种类型的数据。
指针运算
指针+-整数
因为数组在内存中是连续存放的,只要知道第一个元素的地址就可以找到其余的。
#include<stdio.h>
int main()
{
int arr[9] = { 1,2,3,4,5,6,7,8,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = arr;//arr是数组首元素的地址,arr==&arr[0].
int i;
for(i=0;i<sz;i++)
{
printf("%d ", *(p + i));
}
return 0;
}
指针+-指针
注意事项:
1.两个指针一定指向同一区域。
2.指针-指针的绝对值=两个指针之间的元素个数。
int main()
{
int arr[9] = { 1,2,3,4,5,6,7,8,9 };
int* p = arr;
int* pi = &arr[6];//数组地址由低到高
printf("%d ",p - pi);//结果为-6
return 0;
}
指针的关系运算
指针——地址——编号
指针和指针之间是可以比较的
#include<stdio.h>
int main()
{
int arr[9] = { 1,2,3,4,5,6,7,8,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = arr;
while (p < sz + arr)//证明指针之间可以比较
{
printf("%d", *p);
p++;
}
return 0;
}