在这里插入图片描述

#include

int main()
{
	int n = 0x11223344;
	char* pc = (char*)&n;
	*pc = 0;
	return 0;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

在这里插入图片描述

  
  从调试我们可以看到,代码 1 会将 n n n 的 4 个字节全部改为 0 ,而代码 2 只是将 n n n第一个字节改为 0
  

指针的类型决定了对指针解引用时,指针有多大的访问权限(一次能操作几个字节)

例如: c h a r char char* 只能访问 1 个字节, i n t int int* 能访问 4 个字节
  
  

3.2、 指针 ± 整数

  
  让我们先来看一段代码,观察他们的地址变化

#include

int main()
{
	int n = 10;
	char* pc = (char*)&n;
	int* pi = &n;

	printf("&n   =%p\n", &n);
	printf("pc   =%p\n", pc);
	printf("pc+1 =%p\n", pc + 1);
	printf("pi   =%p\n", pi);
	printf("pi+1 =%p\n", pi + 1);

	return 0;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}"> class="hide-preCode-box">

运行结果:

这里是引用

  
  我们可以看到, c h a r char char* 类型 +1 跳过了 1 个字节 i n t int int* 类型 +1 跳过了 4 个字节
  
  这是因为 c h a r char char * 指针类型所指向的 c h a r char char 类型大小是 1 个字节 ,同理, i n t int int * 所指向的 i n t int int 类型大小是 4 个字节
  

指针的类型决定了指针向前或向后走一步有多大

  

3.3、 v o i d void void * 指针

  
  在所有指针类型中,还有一种特殊的指针: v o i d void void * 指针。我们知道 v o i d void void 用在函数的返回类型和参数中时,表示无返回值、无参数,那么 v o i d void void * 指针又表示什么呢?
  
  void * 可以理解为无具体类型的指针(或者叫泛型指针),它可以接收任意类型的地址
    
  但是它也有局限性:void *类型指针不能完成上面的解引用和指针 +- 整数的运算,因为 void *类型指针不知道访问权限(一次应操作几个字节),想完成上述运算,只能先强制类型转换为其他指针类型。

  
举例:

#include

int main()
{
	int a = 10;
	int* pi = &a;
	char* pc = &a;
	return 0;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

在这里插入图片描述
  
  我们可以看到,将一个 i n t int int 类型的变量地址赋值给一个 c h a r char char * 类型的指针变量。编译器给出了警告,因为类型不兼容,要想消除这个警告,除了强制类型转换成 c h a r char char * 类型,还可以用 v o i d void void *类型接收。
  
如下:

#include

int main()
{
	int a = 10;
	void* pi = &a;
	void* pc = &a;

	*pi = 10;
	*pc = 0;
	return 0;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

VS编译器运行结果:
在这里插入图片描述
  我们可以看到,虽然用 v o i d void void * 类型接收编译器并没有报警告,但是却无法解引用,编译器直接报错,那么 v o i d void void * 类型有什么用呢?
  
  一般 v o i d void void * 类型用在函数参数部分,用来接收未知类型数据的地址的,这样设计可以达到泛型编程的效果。使得一个函数可以处理多种类型的数据。

  

四、指针运算

  

指针的基本运算有三种,分别是:

  

5.1、指针 ± 整数

  
  在 C语言——详解数组 一文中,我曾经提到过,数组在内存中是连续存放的。因此,对于数组来说,我们只要找到了他的首元素地址,那他剩下元素的地址也能顺藤摸瓜找到。
  

#include
//指针 +- 整数
int main()
{
	int arr[9] = { 1,2,3,4,5,6,7,8,9 };
	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;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

  

在这里插入图片描述

  

指针 ± 整数公式:

例如:

int a = 10;
int* p = &a;
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

  
p + 1 p + 1 p+1 跳过4 个字节 ( 1 ∗ s i z e o f ( t y p e )) (1 * sizeof(type)) 1sizeoftype))

  
  

5.2、指针 – 指针

  
  指针 – 指针是什么意思呢?我们可以类比生活中的例子:
  
  上面的例子:指针 ± 正数可以类比日期 ± 天数

在这里插入图片描述

  
  同理,指针 – 指针也可类比成日期 – 日期
  

在这里插入图片描述

  
看下面这段代码:

#include

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;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

  这里,我们模拟实现了一个简陋的 s t r l e n strlen strlen 函数
  
  函数来求字符串长度,代码逻辑是:传入字符串首元素的地址(指针),然后找到字符串最后一个元素的地址(指针),两个指针相减,得到的是中间的元素格式,即整个字符串的长度啦。

  
但需要注意的是:

  
例如:

#include

int main()
{
	int arr[10] = { 0 };
	char ch[5] = { 0 };
	printf("%d\n", &ch[4] - &arr[6]);
	return 0;
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

  上述代码是错误的代码,因为两个指针并没有指向同一块空间。
  
  

5.3、指针关系的运算

  
  指针关系运算即地址(指针)与地址(指针)比较大小
  

请看代码:

#include

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++;
	}
}
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

  该代码中,循环条件判断中就运用了指针关系的运算,以确保对数组的访问不越界。

  
  
  


  好啦,本期关于指针就介绍到这里啦,希望本期博客能对你有所帮助,同时,如果有错误的地方请多多指正,让我们在C语言的学习路上一起进步!

data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/yusjushd/article/details/136602669","extend1":"pc","ab":"new"}">>
注:本文转载自blog.csdn.net的9毫米的幻想的文章"https://blog.csdn.net/yusjushd/article/details/136602669"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!