一、指针的简单使用
#include <stdio.h>
void main()
{
int a = 10; //定义一个整型变量a
int* p; //定义整型指针p
p = &a; //指针p指向变量a的地址
//分别打印不同信息
printf("指针P的地址为 : %d\n", p);
printf("指针P的值为 : %d\n", *p);
printf("integer 类型所占用的内存大小为 : %d\n", sizeof(int));
printf("指针(p+1)的地址为 : %d\n", (p + 1));
printf("指针(p+1)的值为 : %d\n", *(p + 1));
}
运行结果如下:
以上代码可实现定义一个整型的指针p 并实现打印
因为指针p指向了变量a的地址 因此p的值也是a的值
由第三段打印信息可得知 整型结构类型占用的内存大小为4字节
但由于整型占用四个字节 因此指针p+1的地址往后推4 为6224988
指针p+1称为 野指针 指向的数据值即为 脏数据
野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)指针变量在定义时如果未初始化,其值是随机的,指针变量的值是别的变量的地址,意味着指针指向了一个地址是不确定的变量,此时去解引用就是去访问了一个不确定的地址,所以结果是不可知的。
该地址没有值因此出现 脏数据 如图第五行
脏数据(Dirty Read)是指源系统中的数据不在给定的范围内或对于实际业务毫无意义,或是数据格式非法,以及在源系统中存在不规范的编码和含糊的业务逻辑。
二、指针类型、算术运算、void指针
1.不同数据类型储存信息的方式
通过之前所学可知,整型占用四个字节,如图:byte0、byte1、byte2、byte3,假设a的首地址为200,则byte0、byte1、byte2、byte3分别如上图所示。
则整型变量a赋值为1025,在byte0内二进制转化为00000001,byte1内二进制存储为00000100,byte2中二进制存储为00000000、byte3中二进制存存储为00000000,在byte3中第一位表示正负号。 则1025=1*2^10+1*2^0.
若指针p取a的地址则为200.代码如下:
#include <stdio.h>
void main()
{
int a = 1025;
int* p;
p = &a;
printf("指针P的地址为 : %d\n", p);
printf("指针P的值为 : %d\n", *p);
printf("integer 类型所占用的内存大小为 : %d\n\n", sizeof(int));
char* p0;
p0 = (char*)p; //强制类型转换
printf("指针p0的地址为 : %d\n", p0);
printf("指针p0的值为 : %d\n", *p0);
printf("char 类型所占用的内存大小为 : %d\n", sizeof(char));
}
运行结果如下:
让我们来分析各个数据是如何得出的:
1.指针p因为指向了变量a,因此指针p的地址也就是变量a的首地址。
2.指针p的地址即变量a的地址,因此其值也对应变量a的值,即1025。
3.整型占用的字节空间为4。
4.指针p0为char(字符型),其指向指针p并且将(int)p进行强制类型转换,转换为(char)p。因此指针p0的首地址与p的首地址相同均为10483832.
5.指针p0的值为1,解释如下:
因为变量a = 1025 :00000000 00000000 00000100 00000001
字符型指针p0指向p时进行强制类型转换,char类型占用一个字节 因此p0只指向了byte0即(00000001),因此 *p0 = 1*2^0 = 1。
6.char类型占用1个字节。
2.定义空指针
代码如下:
#include <stdio.h>
void main()
{
int a = 1025;
int* p;
p = &a;
printf("指针P的地址为 : %d\n", p);
printf("指针P的值为 : %d\n", *p);
void* p0;
p0 = p;
printf("指针p0的地址为 : %d", p0);
}
三、函数的传值与传址
1.函数传值
代码如下:
#include "stdio.h"
void increment(int a)
{
a = a+1;
printf("a的地址为 : %d\n",&a);
printf("a的值为:%d\n",a);
}
int main()
{
int a = 10;
increment(a);
printf("a的地址为 : %d\n",&a);
printf("a的值为:%d\n",a);
}
运行结果如下:
内存底层理解,视频地址(精准空降):【强烈推荐】4小时彻底掌握C指针 - 顶尖程序员图文讲解 - UP主翻译校对 (已完结)_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1bo4y1Z7xf?p=5&t=264.12.函数传址:
代码如下:
#include "stdio.h"
void increment(int *p)
{
*p = *p+1;
printf("increment函数中信息如下:\n");
printf("a的地址为 : %d\n",p);
printf("a的值为:%d\n",*p);
}
int main()
{
int a = 10;
printf("a的值为 : %d\n",a);
increment(&a);
printf("函数传递后a的信息:\n");
printf("a的地址为 : %d\n",&a);
printf("a的值为:%d\n",a);
}
运行结果如下:
内存层理解,视频地址(精准空降):
四、指针和数组
如上图,我们定义一个整型数组A[5],已知int类型占用4个字节,因此数组A占用5*4=20个字节,假设数组A的首地址为200,则数组A的占用地址如上图A[0]-200,A[1]-204,A[2]-208``````
定义一个整型变量x = 5,整型指针p,p指向x假设x的地址为300,则打印p的地址即为300,*p为5,p+1为304,*(p+1)为脏数据。
但若我们令指针p指向数组a的首地址,即p = A,则打印p即200,*p即即2,p+1 == (A+1) == &A[1] = 204,*(p+1) == *(A+1) == A[1] = 4``````
代码如下:
#include <stdio.h>
void main()
{
int A[5] = {2,4,5,8,1};
int *p;
p = A;
printf("指针P的地址为 : %d\n",p);
printf("数组A的首地址为 : %d\n",A);
printf("指针P的值为 : %d\n",*p);
printf("数组A[0]的值为 : %d\n",A[0]);
printf("\n");
printf("指针P+1的地址为 : %d\n",p+1);
printf("数组A[1]的地址为 : %d\n",A+1);
printf("指针P+1的值为 : %d\n",*(p+1));
printf("数组A[1]的值为 : %d\n",A[1]);
}
运行结果如下: