栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言基础:008 C基础语法 - 指针

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言基础:008 C基础语法 - 指针

  1. 指针
    1. 指针 是用来 存放地址 的,地址是唯一标示 一块地址空间 的。 指针的大小在 32 位平台是 4 个字节,在 64 位平台是 8 个字节。
      1. 指针 就是 地址 ; 平时口语中说的指针,通常指的是 指针变量, 是用来 存放内存地址 的变量。
      2. 指针变量
        1. 我们可以通过 &( 取地址操作符)取出 变量 的内存 实际地址 ,把 地址 可以存放到一个变量中,这个 变量就是 指针变量。
        2. 指针变量 ,用来 存放地址 的 变量 。(存放在指针中的值都被当成地址处理)。
        3. code示例
          #include 
          int main()
          {
          	int a = 10;//在内存中开辟一块空间
          	int* p = &a;//对变量a,取出它的地址,可以使用&操作符。
          	//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p就是一个指针变量。
          	printf("%d %d %d %d %d n", p, &p, *p, a, &a);// 869463732 869463768 10 10 869463732
          	return 0;
          }
    2. 在 32 位的机器上,地址是 32 个 0 或者 1 组成二进制序列,那地址就得用 4 个字节的空间来存储,所以 一个指针变量的大小就应该是 4 个字节。 那如果在 64 位机器上,如果有 64 个地址线,那一个指针变量的大小是 8 个字节,才能存放一个地 址。
  2. 指针类型
    1. 指针 +- 整数
      1. 指针的类型 决定了指针 向前或者向后 走 一步 有 多大 ( 距离 )
      2. code示例
        #include 
        int main()
        {
        	char* pc_1 = NULL;  // char* 类型的指针是为了存放 char 类型变量的地址。
        	short* ps_1 = NULL; // short* 类型的指针是为了存放 short 类型变量的地址。
        	int* pi_1 = NULL;   // int* 类型的指针是为了存放 int 类型变量的地址。
        	long* pl = NULL;
        	float* pf = NULL;
        	double* pd = NULL;
        
        	int n = 1111111;
        	printf("%dn", n);     // 1111111
        	char* pc = (char*)&n;
        	int* pi = &n;
        	printf("%dn", n);     // 1111111
        	printf("%pn", &n);    // 000000C7FA05FC74
        	printf("%pn", pc);     // 000000C7FA05FC74
        	printf("%dn", *pc);    // 71
        	printf("%pn", pc + 1); // 000000C7FA05FC75
        	printf("%pn", pi);      // 000000C7FA05FC74
        	printf("%dn", *pi);     // 1111111
        	printf("%pn", pi + 1); // 000000C7FA05FC78
        
        	return 0;
        }
    2. 指针的解引用
      1. 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如: char * 的指针 解引用就只能访问一个字节,而 int * 的指针的 解引用就能访问 四个字节。
      2. code示例
        #include 
        int main()
        {
        	int n = 11223344;
        	char* pc = (char*)&n;
        	int* pi = &n;
        	printf("%dn", n);  // 11223344
        	printf("%pn", &n); // 000000187D50F5B4
        	printf("%pn", pc); // 000000187D50F5B4
        	printf("%dn", *pc);// 48
        	printf("%pn", pi); // 000000187D50F5B4
        	printf("%dn", *pi);// 11223344
        	*pc = 0; //重点在调试的过程中观察内存的变化。
        	*pi = 0; //重点在调试的过程中观察内存的变化。
        	return 0;
        }
  3. 野指针
    1. 野指针概念
      1. 野指针就是 指针指向的位置 是 不可知 的(随机的、不正确的、没有明确限制的)
    2. 野指针成因
      1. 野指针形成的三个原因
        1. 指针未初始化
        2. 指针越界访问
        3. 指针指向的空间释放
      2. code示例
        #include 
        int main()
        {
        	int* p_0;// 1. 指针未初始化:局部变量指针未初始化,默认为随机值
        	*p_0 = 20;
        
        	int arr[10] = { 0 };
        	int* p = arr;
        	int i = 0;
        	for (i = 0; i <= 11; i++)
        	{
        		//2. 指针访问越界:当指针指向的范围超出数组arr的范围时,p就是野指针
        		*(p++) = i;
        	}
        
        	return 0;
        }
    3. 如何规避野指针
      1. 规避野指针的几种方式 1. 指针初始化 2. 小心指针越界 3. 指针指向空间释放即使置NULL 4. 避免返回局部变量的地址 5. 指针使用之前
      2. code示例
        #include 
        int main()
        {
        	int* p = NULL; // 1. 指针初始化
        	int a = 10;
        	p = &a;
        	if (p != NULL) // 5. 指针使用之前检查有效性
        	{
        		*p = 20;
        	}
        	return 0;
        }
  4. 指针运算
    1. 指针有哪些运算
      1. 指针 +- 整数

      2. 指针 - 运算

      3. 指针的关系运算

    2. 实际在绝大部分的编译器上是可以顺利的完成指针关系运算,但应该避免这样写,因为标准规定中并不保证它可行。

    3. 标准规定:
      1. 允许 指向数组元素的指针 与 指向数组最后一个元素后面的那个内存位置的指针 比较,但是 不允许 与 指向第一个元素之前的那个内存位置的指针 进行比较。
    4. code示例
      #define N_VALUES 5
      #include 
      
      int main()
      {
      	char* s = "abc";
      	char* p = s;
      	while (*p != '')
      	{
      		p++; // 1. + 指针
      		printf("%d %pn", *p, p);
      	}
      	
      	// 2. - 指针
      	printf("%p %p %dn",p, s, p - s); // 00007FF676509C23 00007FF676509C20 3
      	
      	float values[N_VALUES];
      	float* vp;
      	for (vp = &values[N_VALUES - 1]; vp >= &values[0]; vp--) {
      		*vp = 0; // 3. 指针的关系运算
      		printf("%d %pn", *vp, vp);
      	}
      	
      
      	return 0;
      }
  5. 指针和数组
    1. 数组名表示的是数组首元素的地址
      1. 数组名和数组首元素的地址是一样的
      2. 把 数组名 当成 地址 存放到一个 指针 中,不仅可以通过 数组下标来访问数组,也可以 使用指针来访问一个数组
    2. code示例
      #include 
      int main()
      {
      	int arr[5] = { 1,2,3 };
      	printf("arr = %pn", arr);         // arr = 000000810BD4FB98
      	printf("&arr[0] = %pn", &arr[0]); // &arr[0] = 000000810BD4FB98
      
      	int* p = arr; // 指针 p 存放的是数组首元素的地址
      	printf("p = %pn", p);  // p = 000000810BD4FB98
      
      	int sz = sizeof(arr) / sizeof(arr[0]); // 5
      	for (int i = 0; i < sz; i++)
      	{
      		printf("&arr[%d] = %p   <====> p+%d = %pn", i, &arr[i], i, p + i);
      		printf("arr[%d] = %d   <====> *(p+%d) = %dn", i, arr[i], i, *(p + i)); // 通过指针来访问数组
      	}
      	
      
      	return 0;
      }
  6. 二级指针
    1. 指针变量 也是变量,是变量就有地址,那 指针变量的地址 存放在哪里?这就是 二级指针 。

       

    2. 二级指针的运算
      1. *ppa 通过对 ppa 中的地址进行 解引用 ,这样找到的是 pa , *pa 访问的就是 pa 。
      2. **ppa 先通过 *ppa 找到 pa , 然后对 pa 进行 解引用 操作,那找到的是 a 。
      3. code示例
        #include 
        int main()
        {
        	int a = 111;
        	int* pa = &a;
        	int** ppa = &pa; // 二级指针
        	// a的地址 = 000000E01CBCF8B4, pa中存放的内容 = 000000E01CBCF8B4
        	printf("a的地址 = %p, pa中存放的内容 = %pn", &a, pa);
        	// pa的地址 = 000000E01CBCF8D8, ppa中存放的内容 = 000000E01CBCF8D8, ppa的地址 = 0000002BF390F668
        	printf("pa的地址 = %p, ppa中存放的内容 = %p, ppa的地址 =  %pn", &pa, ppa, &ppa);
        	int b = 20; 
        	*ppa = &b;//等价于 pa = &b;
        	printf("%pn", &b);          // 0000002BF390F684
        	printf("%p %pn", *ppa, pa); // 0000002BF390F684 0000002BF390F684
        
        	**ppa = 30;
        	//等价于*pa = 30;
        	//等价于a = 30;
        
        	return 0;
        }
  7. 指针数组
    1. 指针数组是数组。是存放指针的数组。
    2. code示例
      #include 
      int main()
      {
      	int arr1[5];
      	char arr2[6];
      	int* arr3[5];//arr3是一个数组,有五个元素,每个元素是一个整形指针。
      
      	return 0;
      }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/949856.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号