C语言学习记录——7000+字长文-复习&学习指针(指针、地址、指针变量、指针与数组、指针与函数、指针数组、多级指针)一

简介: C语言学习记录——7000+字长文-复习&学习指针(指针、地址、指针变量、指针与数组、指针与函数、指针数组、多级指针)一

指针与地址

地址也称内存地址。

概念:

在计算机中,所有的运行数据都存放在内存储器中,内存储器的一个字节占用一个内存单元。为方便访问这些内存单元,我们为每个内存单元进行了编号,这些编号就称为内存地址。

我们简单理解为:内存储器为一个酒店,内存单元是住客们,内存地址就相当于他们所住房间的门牌号。

例如:使用取地址运算符&时,就是在获取变量的内存地址

指针

概念:

根据内存地址就可以找到相应的内存单元,所以通常也把地址称为指针。

看下面的代码:

#include <stdio.h>
int main()
{
  int n;
  int *p = &n;
  printf("%p\n", p);
  return 0;
}

其运行结果为:  0032F824

该结果即是变量n的内存地址,也称为其指针。

 

指针变量

概念:

在C语言中,允许用一个变量来存放指针,这种变量就称为指针变量。

其与一般变量一样,要先声明后使用

定义形式:

类型说明符(数据类型) * 指针变量名;

其中类型说明符表示该指针变量所指向的变量是什么数据类型,* 是指说明符,当*单独使用时,则为解引用操作符。

例如:

#include <stdio.h>
int main()
{
  int n = 5;
  int *p = &n;
  printf("%d\n", *p); //此处对P进行解引用操作,通过p的地址找到变量n
  return 0;
}

运行结果为:   5

需要注意一点的是:* 是单目运算符,结合性为“左结合”,后面只能接指针变量。

 

指针与数组

指针与一维数组

指向一维数组元素的指针

如果定义了一个一维数组,此时再定义一个指针,并把数组的第一个元素的起始地址赋值给该指针,则该指针就指向了这个一维数组。

例如:

#include <stdio.h>
int main()
{
  int arr[5] = { 1,2,3,4,5 },i;
  int *p;
  p = &arr[0];
  for (i = 0; i < 5; i++)
  {
    printf("arr[%d] = %d\n", i, *(p + i));
  
  }
  return 0;
}

其运行结果为:

指针p与一维数组arr的关系

image.png

指针与整数的加减运算

当指针指向数组元素后,加上或减去一个整数n,表示把指针的当前位置(指向某数组元素)向后或向前移动n个元素的位置。

例如:

#include <stdio.h>
int main()
{
  int arr1[5] = { 1,2,3,4,5 };
  float arr2[5] = { 1.0,2.0,3.0,4.0,5.0 };
  int *p;
  float *b;
  p = &arr1[0];
  b = &arr2[0];
  printf("指针加整数前\n%d\n%.2f\n", *p, *b);
  printf("\n");
  p += 3;
  b += 4;
  printf("指针加整数后\n%d\n%.2f\n", *p, *b);
  return 0;
}

其运行结果为:

 

指针的增量运算

指向数组元素的指针变量的值可以改变。如p++是合法的,使得p指向下一个数组元素。而arr++是非法的,因为arr是数组的首地址,是一个常量。

例如:

#include <stdio.h>
int main()
{
  int arr[5] = { 1,2,3,4,5 },*p;
  p = &arr[0];
  printf("增量运算前\n%d\n", *p);
  p++; //或者++p; 
  //此时指针在原来的基础上加上了4(查阅资料,根据VC++6.0编译环境int型数据占4个字节)
  //从而使得指针指向数组的下一个元素
  printf("\n");
  printf("增量运算后\n%d\n", *p);
  return 0;
}

其运行结果为:

 

指针与指针的减法运算

当两个指针指向同一片连续的存储单元时,指针的减法运算的结果是一个整数,其值为这两个指针变量中的地址之差除以数据类型的长度。

例如:

#include <stdio.h>
int main()
{
  //建立一维数组和两个指针变量
  float arr[5] = { 1.0,5.0,2.0,6.0,9.0 },*p,*b;
  p = &arr[4];
  b = &arr[1];
 
  //计算float型数据占多少个字节
  printf("float型数据占%d个字节\n\n", sizeof(arr[0]));
 
  //打印出p和b的地址,不难算出(16进制转10进制来计算)相减之后结果为12
  printf("p中存放的地址:%p\nb中存放的地址:%p\n两个地址相减得到结果为12\n\n", p, b);
 
  //打印出两个指针相减的结果
  printf("两个指针相减的结果为:%d\n(12 / 4)", p - b);
  return 0;
}

其运行结果为:

 

指针与指针的关系运算

当两个指针指向同一片连续的存储单元时,两个指针可以进行关系运算,即表示它们之间的位置关系。

int arr[10],*p,*b;
 
p == b;  //表示判断p和b是否指向同一数组元素
 
p > b;   //表示判断p所指元素是否在b所指元素的后面
 
p < b;   //表示判断p所指元素是否在b所指元素的前面

用这一知识点,将数组arr中n个整数按相反的顺序存放

#include <stdio.h>
#define N 5
int main()
{
  int arr[N], i, tmp, * p, * q;
  printf("请随机输入%d个数字\n", N);
  for (i = 0; i < N; i++)
  {
    printf("第%d个:", i + 1);
    scanf("%d", &arr[i]);
  }
  p = arr;               //p指向数组中的第一个元素
  q = arr + (N - 1);     //q指向数组中的最后一个元素
  while (p < q)          //逆序存放数组中的元素
  {
    tmp = *p;
    *p = *q;
    *q = tmp;
    p++;
    q--;
  }
  printf("逆序输出为:");
  for (i = 0; i < N; i++)
    printf("%d ", arr[i]);
  printf("\n");
  return 0;
}


其运行结果为:

 

指针与二维数组

二维数组的元素及地址

定义一个二维数组int arr[ 3 ][ 4 ];表示二维数组有3行4列共12个元素,在内存中按行存放。

二维数组arr也可以理解为由3个元素组成,即arr[ 0 ]、arr[ 1 ]、arr[ 2 ],而每个元素是一个一维数组,且都包含了4个元素。

二维数组在内存中的存储方式示意图 image.png

通过行指针引用二维数组的元素

行指针

行指针是一种特殊的指针,它专门用于指向一维数组,定义行指针的一般形式如下:

类型说明符(* 指针名) [常量表达式];

其中,类型说明符代表行指针所指一维数组的元素类型,指针名与前面的指针说明*必须用括号括起来,常量表达式是指针所指向的一维数组的长度。

例如:

int arr[3][4];
int (*p)[4] = &arr[0];
//也可以写成int (*p)[4] = arr;

上面语句中定义了一个指向一维数组的指针p,指向包含4个int型元素的一维数组arr[ 0 ]。此时p + 1指向下一个一维数组arr[ 1 ],因此,*(p + 1)+ 2是arr[ 1 ][ 2 ]的地址,那么


*(*(p + 1)+ 2)就是二维数组元素arr[ 1 ][ 2 ]的值

故,以下几种方式都可以表示二维数组元素arr[ i ][ j ].

int arr[3][4], i , j ;
int (*p)[4] = &arr[0];
//二维数组arr,arr首元素的地址p
 
* (*(arr + i) + j);
 
* (*(p + i) + j);
 
p[i][j];

通过列指针引用二维数组的元素

当指针p指向二维数组的首元素之后,p + 1将指向二维数组的第二个元素,p + 2将指向二维数组的第三个元素,以此类推

例如:

#include <stdio.h>
int main()
{
  int arr[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
  int *p = &arr[0][0];
  printf("%d\n", *p);
  printf("%d\n", *(p + 1));
  return 0;
}

其运行结果为:

 

用指针法输入输出二维数组中的各个元素:

 

//行指针法
#include <stdio.h>
int main()
{
  int arr[3][4], i, j;
  int (*ptr) [4] = &arr[0];
  for (i = 0; i < 3; i++)
  {
    for (j = 0; j < 4; j++)
    {
      scanf("%d", *(ptr + i) + j);
    }
  }
  printf("\n");
  for (i = 0; i < 3; i++)
  {
    for (j = 0; j < 4; j++)
    {
      printf("%d\t", *(*(ptr + i) + j));
    }
    printf("\n");
  }
  return 0;
}
//列指针法
#include <stdio.h>
int main()
{
  int arr[3][4],i,j;
  int *p = &arr[0][0];
  for (i = 0; i < 3; i++)
  {
    for (j = 0; j < 4; j++)
    {
      scanf("%d", p+i+j);
    }
  }
  printf("\n");
  for (i = 0; i < 3; i++)
  {
    for (j = 0; j < 4; j++)
    {
      printf("%d\t", *(p + i + j));
    }
    printf("\n");
  }
  return 0;
}

以上运行结果都为:

 

指针与字符数组

字符数组在C语言中可以用字符串常量初始化,也可以整串地输入或输出。

由于指针与数组的等价性,字符指针也有如下特点:


C语言学习记录——7000+字长文-复习&学习指针(指针、地址、指针变量、指针与数组、指针与函数、指针数组、多级指针)二:https://developer.aliyun.com/article/1530355

目录
相关文章
|
20天前
|
存储 编译器 C语言
【c语言】数组
本文介绍了数组的基本概念及一维和二维数组的创建、初始化、使用方法及其在内存中的存储形式。一维数组通过下标访问元素,支持初始化和动态输入输出。二维数组则通过行和列的下标访问元素,同样支持初始化和动态输入输出。此外,还简要介绍了C99标准中的变长数组,允许在运行时根据变量创建数组,但不能初始化。
35 6
|
21天前
|
存储 C语言
【c语言】数据类型和变量
本文介绍了C语言中的数据类型和变量。数据类型分为内置类型和自定义类型,内置类型包括字符型、整型、浮点型等,每种类型有不同的内存大小和取值范围。变量分为全局变量和局部变量,它们在内存中的存储位置也有所不同,分别位于静态区和栈区。通过示例代码和图解,详细阐述了这些概念及其应用。
33 1
|
23天前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
29天前
|
存储 人工智能 BI
C语言:数组的分类
C语言中的数组分为一维数组、多维数组和字符串数组。一维数组是最基本的形式,用于存储一系列相同类型的元素;多维数组则可以看作是一维数组的数组,常用于矩阵运算等场景;字符串数组则是以字符为元素的一维数组,专门用于处理文本数据。
|
24天前
|
存储 C语言
C语言指针与指针变量的区别指针
指针是C语言中的重要概念,用于存储内存地址。指针变量是一种特殊的变量,用于存放其他变量的内存地址,通过指针可以间接访问和修改该变量的值。指针与指针变量的主要区别在于:指针是一个泛指的概念,而指针变量是具体的实现形式。
|
27天前
|
存储 编译器 C语言
C语言:数组名作为类型、作为地址、对数组名取地址的区别
在C语言中,数组名可以作为类型、地址和取地址使用。数组名本身代表数组的首地址,作为地址时可以直接使用;作为类型时,用于声明指针或函数参数;取地址时,使用取地址符 (&),得到的是整个数组的地址,类型为指向该类型的指针。
|
27天前
|
存储 C语言
C语言:一维数组的不初始化、部分初始化、完全初始化的不同点
C语言中一维数组的初始化有三种情况:不初始化时,数组元素的值是随机的;部分初始化时,未指定的元素会被自动赋值为0;完全初始化时,所有元素都被赋予了初始值。
|
29天前
|
C语言
C语言数组
C语言数组
16 0
|
29天前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
31 3
|
C# C语言 C++
从头开始学习c语言
以前的时候学习C语言时候认为C语言不过是一个学习的工具,学习一些理论知识就达到目的了,谁会用这么傻的语言啊,连个界面也没有,不像vb一下子就做出一个窗体来,放上几个按钮就可以了 后来学习C++的时候,认为C++与C是一种完全不同的语言,两者基本没有什么兼容性,当时在学校里看书的时候,一直比较纳闷为会c++的书上会写C++/C语言教程,到了现在才明白,我去C++与C本来就是一体是一脉相承的
1048 0