• C语言--指针初阶


    C语言–指针初阶


    一、指针是什么

    1. 指针是内存单元中一个最小单元的编号,也就是地址,地址唯一标识一块内存空间
    2. 指针的大小是固定的4\8个字节(32位平台\64位平台)
    3. 平时口语的指针,通常指的是指针变量,是用来存放内存地址的变量

    二、指针与内存的关系

    1.什么是内存

    内存就是电脑上的存储设备,例如买电脑的时候会告诉你,这个电脑是4/8/16/32G的内存,程序在运行的时候会加载到内存中,也会使用内存空间
    在这里插入图片描述

    2.什么是指针变量

    在这里插入图片描述

    1. 指针变量是一种变量,是专门用来存放地址的
    2. int* pa = &a; //pa就被称为指针变量,因为a是整型类型,所以pa变量的类型就是int*

    3.指针变量的使用

    #include
    int main()
    {
    	int a = 10;
    	int* pa = &a;
    	printf("%p\n", &a);
    	printf("%p\n", pa);
    	*pa = 20;//*--解引用操作
    	printf("%d\n", a);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4.指针变量的大小如何判断

    对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0);
    那么32根地址线产生的地址就会是:
    在这里插入图片描述

    1. 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。
    2. 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。

    三、指针类型

    1. 指针类型的意义

    1. 指针类型决定了指针进行解引用操作的时候,一次性访问几个字节
    2. char*的指针,解引用访问1个字节
    3. int*的指针,解引用访问4个字节
    4. float*的指针,解引用访问4个字节
      在这里插入图片描述
    5. 指针类型决定指针的步长(指针+1到底跳过几个字节)
      在这里插入图片描述
    6. 对于指针类型的应用(按字节更改变量)
    #include
    int main()
    {
    	int a = 0x11223344;
    	char* pc = (char*)&a;//a是整数类型,用char*访问的时候,要进行强制类型转换
    	int i = 0;
    	for (i = 0; i < 4; i++)//字符类型,+1跳过一个字节
    	{
    		*pc = 0;
    		pc++;
    	}
    	printf("%d", a);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2. 野指针

    概念:野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)

    2.1 野指针的成因

    1. 指针未初始化
    int main()
    {
        int* p;
        *p = 20;
        renturn 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    p是一个局部变量,没有初始化,里边是随机值

    1. 指针的越界访问
    #include
    int main()
    {
    	int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
    	int* p = arr;
    	int i = 0;
    	for (i = 0; i <= 10; i++)
    	{
    		printf("%d ", *p);
    		p++;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    1. 指针指向的空间释放
      在这里插入图片描述

    2.2 如何避免野指针

    1. 指针初始化
    #include
    int main()
    {
    	int a = 10;
    	int* pa = &a;//指针的初始化
    	
    	int* p = NULL;//NULL-空指针,专门用来初始化指针
    	if (p != NULL)
    	{
    		//这是指针的正确用法,如果直接对空指针进行赋值操作
    		//*p = 20; 这样是不会成功的,因为NULL代表空,空指针也是地址,只是不能使用的地址
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 小心指针越界
    2. 指针指向空间释放,及时置NULL
    3. 避免返回局部变量的地址
    4. 指针使用之前检查有效性

    四、指针的运算

    1. 指针 ± 整数

    #define _CRT_SECURE_NO_WARNINGS 1
    #include
    #define N_VALUES 5
    int main()
    {
    	float values[N_VALUES];
    	float* vp;
    	//指针+-整数;指针的关系运算
    	for (vp = &values[0]; vp < &values[N_VALUES];)
    	{
    		*vp++ = 0;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    2. 指针-指针

    • 前提是两个指针要指向同一块空间(指针类型要相同)

    • 指针-指针的绝对值,得到的是两个指针之间的元素个数

    #include
    int main()
    {
    	int arr[10] = { 0 };
    	printf("%d\n", &arr[9] - &arr[0]);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    2.1 案例一:求字符串的长度

    #define _CRT_SECURE_NO_WARNINGS 1
    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述
    采用指针相减的方法

    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3. 指针的关系运算

    3.1 案例一:指针比较大小

    #include
    #define N_VALUES 5
    int main()
    {
    	float values[N_VALUES];
    	float* vp;
    	for (vp = &values[N_VALUES]; vp > &values[0]; )
    	{
    		*--vp = 0;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    五、指针与数组的关系

    1. 指针和数组是不同的对象
      指针是一种变量,存放地址的,大小是4/8字节的
      数组是一组相同类型元素的集合,是可以存放多个元素的,大小取决于元素个数和元素的类型

    2. 数组的数组名是数组首元素的地址,地址是可以存放在指针变量中,可以通过指针访问数组

    #include
    int main()
    {
    	int arr[10] = { 0 };
    	int* p = arr;
    	int i = 0;
    	int sz = sizeof(arr) / sizeof(arr[0]);
    	for (i = 0; i < sz; i++)
    	{
    		*p = i + 1;
    		p++;
    	}
    	p = arr;
    	for (i = 0; i < sz; i++)
    	{
    		printf("%d ", *p);
    		p++;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    六、二级指针

    #include
    int main()
    {
        int a = 10;
        int * pa = &a;
        int * * ppa = &pa;//ppa就是二级指针
        int** *pppa = &ppa;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    七、指针数组

    指针数组是数组,是存放指针的数组

    #include
    int main()
    {
    	//int arr[5] = { 1,2,3,4,5 };
    	int a = 10;
    	int b = 20;
    	int c = 30;
    	int d = 40;
    	int f = 50;
    	int* arr[5] = { &a,&b,&c,&d,&f };
    	int i = 0;
    	for (i = 0; i < 5; i++)
    	{
    		printf("%d ", *(arr[i]));
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1. 使用指针数组模拟3行4列的数组

    #include
    int main()
    {
    	int a[] = { 1,2,3,4 };
    	int b[] = { 2,3,4,5, };
    	int c[] = { 3,4,5,6 };
    	int* arr[3] = { a,b,c };
    	int i = 0;
    	for (i = 0; i < 3; i++)
    	{
    		int j = 0;
    		for (j = 0; j < 4; j++)
    		{
    			printf("%d ", arr[i][j]);
    		}
    		printf("\n");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

  • 相关阅读:
    安卓四大组件:ContentProvider
    Thread类的start()方法创建线程的底层分析
    SMI 与 Gateway API 的 GAMMA 倡议意味着什么?
    vulhub中GitLab 远程命令执行漏洞复现(CVE-2021-22205)
    接口测试项目(非常值得练手)
    jvm调优-cpu飙升及响应慢
    python之使用深度学习创建自己的表情符号
    软件测试---
    Vue3——区域内无限滚动
    es6运算符
  • 原文地址:https://blog.csdn.net/Senyu_nuanshu/article/details/132733706