目录
2.1 指针的大小 :在32位平台是4个字节,在64位平台是8个字节。
2.2.1 意义1:指针的类型决定了指针在被解引用的时候可以访问几个字节
2.2.2 意义2: 指针的类型决定了指针+-1操作的时候,跳过几个字节,即指针的步长。
1. 指针是什么
1、每个内存单元都有一个编号,把内存单元的编号就称为地址(地址也叫指针)
指针其实就是地址,地址就是编号,指针就是内存单元的编号。
2、平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量。
3、指针的大小在32位平台是4个字节,在64位平台是8个字节。
(原因:在32位的机器上,地址是32个0或者1(32个bite)组成二进制序列,那地址就得用4个字节(1byte = 8 bit)的空间来存储,所以 一个指针变量的大小就应该是4个字节。 那如果在64位机器上,有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。 )
2. 指针和指针类型
2.1 指针的大小 :在32位平台是4个字节,在64位平台是8个字节。
当不知道给这个指针赋值什么时,就赋值为NULL 。
sizeof 返回值的类型是无符号整型 unsigned int,严格意义上打印时应该用%u,不能用%d,
%zu打印最准确,%zu本身就是给sizeof准备的一种格式打印。
#include <stdio.h>
int main()
{
//当不知道给这个指针赋值什么时,就赋值为NULL
char* pc = NULL;
short* ps = NULL;
int* pi = NULL;
double* pg = NULL;
//sizeof 返回值的类型是无符号整型 unsigned int,严格意义上打印时应该用%u,不能用%d
//%zu打印最准确,%zu本身就是给sizeof准备的一种格式打印
printf("%zu\n",sizeof(pc));
printf("%zu\n", sizeof(short*));
printf("%zu\n", sizeof pi);
printf("%zu\n", sizeof(pg));
return 0;
}
×86: (32位)指针的大小在32位平台是4个字节
×64: (64位)指针的大小在64位平台是8个字节
2.2 指针类型的意义
1个16进制位是4个二进制位(比特位)
2个16进制位是8个二进制位,也就是1个字节
存0x11223344这个16进制数字刚好需要4个字节(int类型是4个字节)
2.2.1 意义1:指针的类型决定了指针在被解引用的时候可以访问几个字节
指针的类型决定了指针在被解引用的时候可以访问几个字节
如果是int*的指针,解引用访问4个字节
如果是char*的指针,解引用访问1个字节
图解:
2.2.2 意义2: 指针的类型决定了指针+-1操作的时候,跳过几个字节,即指针的步长。
指针的类型决定了指针+-1操作的时候,跳过几个字节,即指针的步长。
如果是int*的指针,+1跳过4个字节
如果是char*的指针,+1跳过1个字节
当然,指针不仅可以+-1,指针+-整数时也很类似。
#include <stdio.h>
int main()
{
int a = 0x11223344;
int* pa = &a;
char* pc = (char*)&a;
printf("pa = %p\n",pa);
printf("pa+1 = %p\n", pa+1);
printf("pc = %p\n",pc);
printf("pc+1 = %p\n", pc+1);
return 0;
}
3. 野指针
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
3.1 野指针成因
1. 指针未初始化
2. 指针越界访问
int main()
{
int arr[10] = { 0 };
int* p = arr;//&arr[0]
int i = 0;
for (i = 0; i <= 10; i++)
{
*p = i;
p++;
}
return 0;
}
3. 指针指向的空间释放 ![](https://i-blog.csdnimg.cn/blog_migrate/59fb5c92858aaf232ede356731c87791.png)
3.2 如何规避野指针
1. 指针初始化
2. 小心指针越界
3. 指针指向空间释放及时置NULL
4. 避免返回局部变量的地址
5. 指针使用之前检查有效性
4. 指针运算
4.1 指针+-整数
将数组中的元素都赋值为1:(下面代码都可行)
int main()
{
int arr[10] = { 0 };
int i = 0;
//数组下标的写法
for (i = 0; i < 10; i++)
{
arr[i] = 1;
}
return 0;
}
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*p = 1;
p++;
}
return 0;
}
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
*(p + i) = 1;
}
return 0;
}
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for ( ;p<&arr[10]; )
{
*p++ = 1;//也可以写成 *p = 1; p++;
//(*p)++;是对p指向的内容进行+1,两者不一样
}
return 0;
}
4.2 指针-指针
指针 - 指针的绝对值得到的是指针和指针之间元素的个数
当然,不是所有的指针都能相减,指向同一块空间的2个指针才能相减!!!
int main()
{
int arr[10] = { 0 };
printf("%d\n", &arr[9] - &arr[0]);//9
return 0;
}
例子:自定义函数求字符串的长度
方法一:
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n",len);
return 0;
}
方法二:递归
int my_strlen(char* str)
{
if (*str != '\0')
return 1 + my_strlen(str + 1);
else
return 0;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
方法三:指针-指针 (得到指针和指针之间元素的个数,可以得到字符串的长度)
int my_strlen(char* str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return (str - start);
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
运行结果:
4.3 指针的关系运算 (比较大小)
标准规定: 允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
例如: 将数组中的元素都赋值为1
这种做法可以:
int main()
{
int values[5] = { 0 };
int* vp;
for (vp = &values[5]; vp > &values[0];)
{
*--vp = 1;//可以写成 --vp; *vp = 1;
}
return 0;
}
这种做法不行:
int main()
{
int values[5] = { 0 };
int* vp;
for (vp = &values[4]; vp >= &values[0];vp--)
{
*vp = 1;
}
return 0;
}
5. 指针和数组
arr[i] 等于 *(p+i) 等于 *(arr+i)
例子:打印数组中的所有元素:
下面三种方式都可以。
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int* p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int* p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", *(arr + i));
}
return 0;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int* p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", *(p + i));
}
return 0;
}