内存与地址
1.地址的概念
众所周知数据需要在内存中读取,那么我们当我们需要找这个内存时该怎么办?其实在计算机中每个内存单元都有一个编号,有了这个编号CPU可以快速找到内存空间,在这里我们将这个编号叫做地址,在c语言中给地址起了一个新名字————指针。
2.指针变量
1.取地址操作符(&)
有了&后我们可以直接得到变量的地址。
#include<stdio.h>
int main()
{
int a = 10;
printf("%p\n", &a);
return 0;
}
如此我们便可以取出a变量的地址。
2.解引用操作符(*)
我们可以将一个地址存储在一个指针变量中
例如
int a = 10;
int * pa = &a;
便可以将取出的整型变量a的地址取出并存放在指针变量pa中。 那我们该如何取出a中的值呢?
只需要在指针变量的前面加上解引用操作符(*)即可。例如*pa=10
3.指针变量的类型
指针变量的⼤⼩和类型⽆关,只要是指针变量,在同⼀个平台下,⼤⼩都是⼀样的。 我们常用的指针类型有
char*,int*,void*
。
指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)。
char*
的指针解引⽤只能访问⼀个字节,⽽
int* 的指针的解引⽤就能访问四个字节。并且指针的类型决定了指针向前或者向后⾛⼀步有多⼤。
4.指针的运算
指针的基本运算有三种,分别是:
1.指针+- 整数
因为数组在内存中是连续存放的,只要知道第⼀个元素的地址,通过
指针+- 整数
就能找到后⾯的所有元素。
#include <stdio.h>
//指针+- 整数
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
for(i=0; i<sz; i++)
{
printf("%d ", *(p+i));//p+i 这⾥就是指针+整数
}
return 0;
}
2.指针-指针
这种运算可以算出数组中的两个地址之间的元素数量。
//指针-指针
#include <stdio.h>
int my_strlen(char *s)
{
char *p = s;
while(*p != '\0' )
p++;
return p-s;
}
int main()
{
printf("%d\n", my_strlen("abc"));
return 0;
}
3.指针的关系运算
//指针的关系运算
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int *p = &arr[0];
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);
while(p<arr+sz) //指针的⼤⼩⽐较
{
printf("%d ", *p);
p++;
}
return 0;
}
3.数组与指针
1.数组名的理解
我们可以使⽤
&arr[0]
的⽅式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,⽽且
是数组⾸元素的地址。
一般而言数组名就是首元素地址,但还是有两个例外
1.sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩,单位是字节
2.&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素的地址是有区别的)
2.使⽤指针访问数组
int arr[10] = {1,2,3,5,8};
int* p = arr;
如此便可以使用指针变量访问数组。
3.⼆级指针
指针变量也是变量,是变量就有地址,这就是 ⼆级指针 。
如果需要解引用便需要
**p *p
4.指针数组
指针数组就是一个存放了指针的数组
数组中每个元素都是地址,都指向了别的元素。