您的位置:首页 > 健康 > 美食 > 河北 邢台_网页设计模板网站免费下载_seo网站关键词优化报价_东莞seo外包平台

河北 邢台_网页设计模板网站免费下载_seo网站关键词优化报价_东莞seo外包平台

2024/12/23 19:10:20 来源:https://blog.csdn.net/lxy370198409/article/details/144552894  浏览:    关键词:河北 邢台_网页设计模板网站免费下载_seo网站关键词优化报价_东莞seo外包平台
河北 邢台_网页设计模板网站免费下载_seo网站关键词优化报价_东莞seo外包平台

文章目录

  • 一、普通数组与指针数组
  • 二、二维数组与数组指针(指向数组的指针)
  • 三、字符数组与字符指针
  • 四、数组名和&数组名的区别
    • 1、数组名
    • 2、取地址数组名(&数组名)
    • 3、举例

一、普通数组与指针数组

  • 普通数组
    • 例如int arr[5];,这是一个简单的一维数组,它包含5个int类型的元素。从类型角度看,arr的类型是int [5],表示一个包含5个int元素的数组。在内存中,这些元素是连续存储的,数组名arr在大多数情况下代表数组的首地址。
    • 当我们使用arr作为表达式时,在很多情况下它会“衰减”为一个指向数组首元素的指针,类型变为int *。例如,当把arr传递给一个函数时,函数接收到的实际是一个int *类型的指针,指向数组的首元素。
  • 指针数组
    • 定义形式为类型 *数组名[数组大小];,例如int *pArr[3];。这里pArr是一个数组,它的元素类型是int *,即每个元素都是一个指向int类型的指针。
    • 假设我们有三个int变量a = 1, b = 2, c = 3,可以这样使用pArrint *pArr[3] = {&a, &b, &c};,此时pArr[0]指向apArr[1]指向bpArr[2]指向c。这种数组主要用于存储多个指针,方便对这些指针所指向的对象进行操作。

二、二维数组与数组指针(指向数组的指针)

  • 二维数组
    • 例如int twoDArr[3][4];,这是一个二维数组,它的类型是int [3][4],可以看作是一个包含3个元素的数组,每个元素又是一个包含4个int元素的数组。在内存中,它的存储方式是按行存储,即先存储第一行的4个元素,再存储第二行的元素,以此类推。
    • 当我们使用twoDArr作为表达式时,它也会衰减,不过它衰减后的类型是int (*)[4](指向包含4个int元素的数组的指针)。例如,在函数参数传递中,如果有一个函数接收一个二维数组作为参数,形式参数可以写成void func(int (*p)[4]),这里p就是一个数组指针,它可以接收二维数组twoDArr作为实参。
  • 数组指针(指向数组的指针)
    • 定义形式为类型 (*指针变量名)[数组大小];,如int (*p)[4];。这种指针是专门用于指向一个包含特定数量元素(这里是4个int元素)的数组。
    • 假设我们有一个二维数组int arr[3][4],可以通过以下方式使用数组指针:
int (*p)[4];
p = arr;
for(int i = 0; i < 3; i++){for(int j = 0; j < 4; j++){// 访问二维数组元素printf("%d ",(*(p + i))[j]);}printf("\n");
}
 - 这里`p`指向`arr`的首行(即一个包含4个`int`元素的数组),`p + i`指向第`i`行,`(*(p + i))[j]`就相当于`arr[i][j]`,- 通过这种方式可以使用数组指针来访问二维数组。

三、字符数组与字符指针

  • 字符数组
    • 例如char str1[] = "hello";,这是一个字符数组,它的类型是char [6](包括字符串结束符\0)。字符数组在内存中有自己的存储空间,用于存储字符序列。
    • 可以通过下标来访问数组中的字符,如str1[0]表示字符'h'。而且字符数组可以通过strcpy等函数来修改其中的内容。
  • 字符指针
    • 定义形式为char *str2;,如果str2 = "world";,这里str2是一个字符指针,它指向一个字符串常量(在C语言中,字符串常量存储在只读数据区)。其类型是char *
    • 虽然可以通过str2来访问字符串中的字符,如printf("%c", str2[0]);会输出'w',但是不能通过str2来修改字符串常量的内容(在标准C语言环境下,这样做是未定义行为)。如果想修改字符串内容,需要通过字符数组来实现。例如,char str3[] = "test";,可以通过str3[0]='T';来修改。

四、数组名和&数组名的区别

1、数组名

  • 代表首元素地址(大部分情况):在C和C++语言中,数组名在大多数情况下会“衰减”为指向数组首元素的指针。例如,对于int arr[5];arr通常等价于&arr[0],它们的类型都是int*。这意味着可以使用数组名来访问数组中的元素,就像使用指针一样。例如,可以通过*(arr + 1)来访问arr[1]
  • 类型信息(数组类型):尽管数组名在很多操作中表现得像指针,但它本身的类型是“数组类型”。对于int arr[5];arr的类型是int [5]。这个类型信息在一些特定的场景下会体现出来,比如在使用sizeof运算符时,sizeof(arr)返回的是整个数组所占用的字节数(在这个例子中是5 * sizeof(int)),而不是指针的大小。
  • 作为函数参数:当数组名作为函数参数传递时,它会被转换为指向数组首元素的指针。例如,有一个函数void func(int a[]),实际上它等价于void func(int *a)。这是因为在函数调用过程中,传递的是数组的首元素地址,而不是整个数组的副本。

2、取地址数组名(&数组名)

  • 代表整个数组的地址:对于int arr[5];&arr返回的是整个数组的地址。它的类型是int (*)[5],这是一个指向包含5个int元素的数组的指针。与arr(大部分情况下等价于&arr[0])不同,&arr的地址值在数值上虽然和&arr[0]相同,但它们的类型和含义是不同的。
  • 在指针运算中的差异:因为&arr是整个数组的地址,所以在指针运算中会有不同的行为。例如,如果p是一个指向整个数组的指针(类型为int (*)[5]),那么p + 1会跳过整个数组的长度(即5 * sizeof(int)字节),而如果q是一个指向数组首元素的指针(类型为int*),那么q + 1只会跳过一个元素的长度(即sizeof(int)字节)。
  • 在函数参数传递中的特殊用途:当想要传递整个数组(而不是仅仅传递数组的首元素地址)给一个函数时,可以使用指向数组的指针作为参数类型。例如,void func(int (*p)[5])这个函数可以接收一个指向包含5个int元素的数组的指针。在调用这个函数时,可以使用func(&arr),这里&arr就是整个数组的地址。这种方式在处理多维数组等复杂情况时非常有用,能够更准确地操作数组。

3、举例

  1. 示例代码
#include <stdio.h>
int main() {int arr[5] = {1, 2, 3, 4, 5};int *p1 = arr; int (*p2)[5] = &arr;// 输出数组名和取地址数组名的值(地址值)printf("arr: %p\n", (void *)arr);printf("&arr: %p\n", (void *)&arr);// 指针运算的区别printf("p1 + 1: %p\n", (void *)(p1 + 1));printf("p2 + 1: %p\n", (void *)(p2 + 1));// 通过数组名和取地址数组名访问数组元素printf("*(arr + 2): %d\n", *(arr + 2));printf("(*(&arr))[2]: %d\n", (*(&arr))[2]);return 0;
}
  • 运行结果:
    在这里插入图片描述
  1. 详细讲解
    • 指针定义部分
      • int *p1 = arr;:这里将p1定义为一个int类型的指针,并将arr赋值给p1。由于数组名arr在这种情况下会衰减为指向首元素的指针,所以p1现在指向arr的第一个元素1
      • int (*p2)[5] = &arr;p2被定义为一个指向包含5个int元素的数组的指针,然后将&arr(整个数组的地址)赋值给p2
    • 输出地址值部分
      • printf("arr: %p\n", (void *)arr);printf("&arr: %p\n", (void *)&arr);:这两行代码分别输出数组名arr的值(也就是首元素的地址)和取地址数组名&arr(整个数组的地址)。在很多情况下,这两个地址值在数值上是相同的,但它们的类型不同。
    • 指针运算部分
      • printf("p1 + 1: %p\n", (void *)(p1 + 1));:因为p1是指向int类型的指针,所以p1 + 1会使指针向后移动一个int类型元素的大小。在这个例子中,如果int类型占4个字节,那么p1 + 1指向的地址会比p1的地址增加4个字节,也就是指向数组中的第二个元素2
      • printf("p2 + 1: %p\n", (void *)(p2 + 1));p2是指向包含5个int元素的数组的指针,所以p2 + 1会使指针向后移动一个包含5个int元素的数组的大小。如果int类型占4个字节,那么p2 + 1指向的地址会比p2的地址增加5 * 4 = 20个字节,这就跳过了整个arr数组。
    • 访问数组元素部分
      • printf("*(arr + 2): %d\n", *(arr + 2));:这里利用数组名arr衰减为指向首元素的指针的特性,arr + 2表示指向数组中第三个元素的指针,然后通过*(arr + 2)来获取这个元素的值,即3
      • printf("(*(&arr))[2]: %d\n", (*(&arr))[2]);:首先&arr是整个数组的地址,*(&arr)就相当于arr(整个数组),然后(*(&arr))[2]就相当于arr[2],所以输出的值也是3

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com