《C语言指针进阶》:字符指针、数组指针、指针数组、数组传参和指针传参、函数指针、函数指针数组、函数指针数组的指针

您所在的位置:网站首页 c语言传递指针数组 《C语言指针进阶》:字符指针、数组指针、指针数组、数组传参和指针传参、函数指针、函数指针数组、函数指针数组的指针

《C语言指针进阶》:字符指针、数组指针、指针数组、数组传参和指针传参、函数指针、函数指针数组、函数指针数组的指针

2024-07-17 21:46| 来源: 网络整理| 查看: 265

指针可以说是在C语言中非常重要的一个知识点,同时也是一道比较难以理解的一块内容。在刚学习指针的时候,我们已经了解了指针的一些基本概念:

指针就是个变量,用来存放地址,地址唯一标识一块内存空间。指针的大小是固定的4/8个字节(32位平台/64位平台)。指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。指针的运算。

相较于一些其他的语言来说,C语言中的指针独具一格,可以说它是C语言的灵魂所在,本篇文章创作目的旨在让想进一步了解指针运用的小伙伴能有所收获,同时如果大家对指针的某些内容不太熟悉或遗忘,能够为大家提供参考和回顾的作用。

一、字符指针

在指针的类型中我们知道有一种指针类型为字符指针 char*。一般使用如下所示

1.单纯用于指向某个字符型变量   int main() { char ch = 'w'; char *pc = &ch; *pc = 'w'; return 0; }

值得说明的是字符指针所指向的字节大小时1个字节(任何一种指针所指向空间的大小是由它的类型决定的,例如除字符指针外int*、double*每次指向的空间大小单位分别为4个字节和8个字节)。因此如果我们想通过字符指针来改变一个整形类型的值时,应该使用4次字符指针。

2.用于模拟字符串数组 int main() { const char* pstr = "hello word.";//这里是把一个字符串放到pstr指针变量里了吗? printf("%s\n", pstr); return 0; }

上述代码运行后输出“hello world”。那么我们应该如何来理解 上述的代码呢?

首先const修饰的指针,说明*pstr的内容是不可改变的。之所以这样声明,是因为讲一段字符串复制给指针与数组是有区别的:简单来讲如果赋值给数组,那么这段字符串中的内容是是可变的;而如果是直接使用指针指向这段字符串,那么这段字符串就相当于是一个字符串常量,其内容是不可改变的,因此我们常常会使用const关键字进行修饰。

其次我们知道指针指向的字符串,实质上是指向字符串首个字符的地址,之所以能够使用“%s”进行打印,是因为这里的指针的作用就相当于是字符型数组的数组名。

知识拓展:当两个不同的字符型指针所指向的字符串内容相同时,两个指针所指向的地址空间是否相同呢?例如下面这段代码,情分析输出的结果是什么?

#include int main() { char str1[] = "hello bit."; char str2[] = "hello bit."; const char *str3 = "hello bit."; const char *str4 = "hello bit."; if(str1 ==str2) printf("str1 and str2 are same\n"); else printf("str1 and str2 are not same\n"); if(str3 ==str4) printf("str3 and str4 are same\n"); else printf("str3 and str4 are not same\n"); return 0; }

当需要推断上述程序输出结果时,首先我们得先理解if条件语句中所表示的含义。两个if条件中所比较的内容分别是两个数组名和连个字符型指针变量,而不论是那种情况,实质上所比较的都是地址所在的位置,因此如果地址相同则输出if中的内容,否则输出else中的内容。

再明白程序的含义之后,我们很清楚的知道不同的数组名所存储的地址是不相同的,因此第一个比较输出的结果应该是:“str1 and str2 are not same”。那么指针是否如同数组名一样呢?

接下来让我们一起验证一下实际结果:

我们惊讶的发现这里str3和str4指向的是一个同一个常量字符串。也就是说C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。

二、指针数组

指针数组顾名思义:它是一个数组,并且数组中存放的内容是指针。

为了让大家具体的了解其含义,一下是几种不同的指针数组:

int* arr1[10]; //存放整形指针的数组 char *arr2[4]; //存放字符指针的数组 char **arr3[5];//存放二级字符指针的数组 三、数组指针 1.数组指针的定义

数组指针他并不是数组而是一种指针,他所指向的对象是数组。

在此之前我们先回顾一下指针的基础内容:

整形指针: int * pint; 能够指向整形数据的指针。 浮点型指针: float * pf; 能够指向浮点型数据的指针

那么能够指向数组的数组指针是如何声明的呢?下面我们将声明一个指向含有10个元素的整型数组指针:

int (*p)[10]; //解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个 //指针,指向一个数组,叫数组指针。 //这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。 2.&数组名VS数组名

对于下面的数组:

int arr[10];

arr 和 &arr 分别是啥? 我们知道arr是数组名,数组名表示数组首元素的地址。那&arr数组名到底是啥?如果arr与&arr是完全相同的,&arr也是表示的数组的首元素地址,那这样做不会显得很多余吗,我们应该如何看待&arr呢?

我们不妨先来看一段代码:

#include int main() { int arr[10] = {0}; printf("%p\n", arr); printf("%p\n", &arr); return 0; }

所显示输出结果如下,可以看出打印的地址是相同的,可能在这里有些认为数组名和&数组名是相同的小伙伴心里比较开心了,不过小风想说先别急哈,好戏还在后头呢!

我们再看一段代码:

#include int main() { int arr[10] = { 0 }; printf("arr = %p\n", arr); printf("&arr= %p\n", &arr); printf("arr+1 = %p\n", arr+1); printf("&arr+1= %p\n", &arr+1); return 0; }

结果输出的结果如下:

看见这个结果是不是很出乎大家的意料呢?根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。实际上: &arr 表示的是整个数组的地址,而不是数组首元素的地址。 本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40。(望诸君牢记)

3.数组指针的应用

那数组指针是怎么使用的呢? 既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。

#include int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,0}; int (*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p //但是我们一般很少这样写代码 return 0; }

上述的代码其实很少这样来使用数组指针,主要是为了让大家理解其含义。数组指针的应用通常可以用来接收二维数组参数的传递,例如下面代码(可以参照print_arr1来理解print_arr2,两者实现的功能是完全一样的)

#include void print_arr1(int arr[3][5], int row, int col) { int i = 0; for(i=0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3