指针(二)------字符指针+数组指针+指针与数组(传参)

简介: 指针(二)------字符指针+数组指针+指针与数组(传参)

前言

指针(一)中,我们已经知道了指针的基本用法:

1.指针就是一个用于存放地址的变量,地址唯一标识一块内存空间。

2.指针的大小是固定的4/8个字节(32位平台/64位平台)。

3.指针是有类型的,指针的类型决定了指针±整数的步长和指针解引用操作时的权限大小。

4.指针的相关运算。

今天,我们继续来学习指针更深层次的内容。


字符指针

在指针的类型中有一种指针类型叫字符指针char * 。

使用方法为:

#include<stdio.h>
int main()
{
  char ch = 'w';
  char* p = &ch;
  return 0;
}

代码中,将字符变量ch的地址存放在了字符指针p中。

字符指针还有另一种使用方式:

#include<stdio.h>
int main()
{
  char* p = "hello csdn.";
  printf("%c\n", *p);//打印字符'h'
  printf("%s\n", p);//打印字符串"hello csdn."
  return 0;
}

字符指针p中存放的并非字符串"hello csdn.",字符指针p中存放的是字符串"hello csdn.“的首元素地址,即字符’h’的地址。

所以,当对字符指针p进行解引用操作并以字符的形式打印时只能打印字符’h’。我们知道,打印一个字符串只需要提供字符串的首元素地址即可,既然字符指针p中存放的是字符串的首元素地址,那么我们只要提供p(字符串首地址)并以字符串的形式打印,便可以打印字符串"hello csdn.”。

注意:代码中的字符串"hello csdn."是一个常量字符串。

指针数组

指针数组也是数组,是用于存放指针的数组。

int* arr3[5];

以此内推:

char* arr4[10];//数组arr4包含10个元素,每个元素是一个一级字符型指针。
char** arr5[5];//数组arr5包含5个元素,每个元素是一个二级字符型指针。

数组arr4包含10个元素,每个元素是一个一级字符型指针;数组arr5包含5个元素,每个元素是一个二级字符型指针

数组指针

定义

整型指针是指向整型的指针,字符指针是指向字符的指针,那么依次内推:数组指针应该就是指向数组的指针了。

整型指针和字符指针,在使用时只需取出某整型/字符型的数据的地址,并将地址存入整型/字符型指针即可。

#include<stdio.h>
int main()
{
  int a = 10;
  int* pa = &a;//取出a的地址存入整型指针中
  char ch = 'w';
  char* pc = &ch;//取出ch的地址存入字符型指针中
  return 0;
}

数组指针也是一样,我们只需取出数组的地址,并将其存入数组指针即可。

#include<stdio.h>
int main()
{
  int arr[10] = { 0 };
  int(*p)[10] = &arr;
  //&arr - 数组的地址
  return 0;
}

那么数组指针的指针类型是如何写出来的呢?

我们应该知道的是:

1. [ ]的优先级要高于 * 。

2. 一个变量除去了变量名,便是它的变量类型。比如:

int a = 10;//除去变量名a,变量类型为int
char ch = 'w';//除去变量名ch,变量类型为char
int* p = NULL;//除去变量名p,变量类型为int*

数组其实还可以这样理解:

int arr[10] = { 0 };//除去变量名arr,变量类型为int [10]
int arr[3][4] = { 0 };//除去变量名arr,变量类型为int [3][4]
int* arr[10] = { 0 };//除去变量名arr,变量类型为int* [10]

3. 一个指针变量除去了变量名和 * ,便是指针指向的内容的类型。比如:

int a = 10;
int* p = &a;//除去变量名(p)和*,便是P指向的内容(a)的类型->int
char ch = 'w';
char* pc = &ch;//除去变量名(pc)和*,便是pc指向的内容(ch)的类型->char

知道这些,我们可以来写一个数组指针的指针类型:

#include<stdio.h>
int main()
{
  int arr[10] = { 0 };
  int(*p)[10] = &arr;
  //&arr - 数组的地址
  return 0;
}

数组名与&

数组名代表整个数组的地址的情况其实只有两种

1.&数组名。

2.数组名单独放在sizeof内部,即sizeof(数组名)。

除此之外,所有的数组名都是数组首元素地址。

例如:

int arr[5] = { 1, 2, 3, 4, 5 };

对于该数组arr,只有以下两种情况数组名代表整个数组的地址:

&arr;
  sizeof(arr);//arr单独放在sizeof内部

除此之外,所以的arr都代表数组首元素地址,即1的地址

我们指针联系起来就是:

#include<stdio.h>
int main()
{
  int arr[5] = { 1, 2, 3, 4, 5 };
  int* p1 = arr;//数组首元素的地址
  int(*p2)[5] = &arr;//数组的地址
  printf("%p\n", p1);
  printf("%p\n", p2);
  printf("%p\n", p1+1);
  printf("%p\n", p2+1);
  return 0;
}

因为代码中的arr是数组首元素地址,所以要用int * 的指针接收。而&arr是整个数组的地址,所以要用数组指针进行接收。

虽然一个是数组首元素地址,一个是数组的地址,但是它们存放的都是数组的起始位置的地址,所以将p1和p2以地址的形式打印出来发现它们的值一样。

数组首元素地址和数组的地址的区别在于,数组首元素地址+1只能跳过一个元素指向下一个元素,而数组的地址+1能跳过整个数组指向数组后面的内存空间。

数组指针的应用

最简单的应用就是打印二维数组

#include<stdio.h>
void print(int(*p)[5], int row, int col)
{
  int i = 0;
  for (i = 0; i < row; i++)//行数
  {
    int j = 0;
    for (j = 0; j < col; j++)//列数
    {
      printf("%d ", *(*(p + i) + j));
    }
    printf("\n");//打印完一行后,换行
  }
}
int main()
{
  int arr[3][5] = { { 1, 2, 3, 4, 5 }, { 2, 3, 4, 5, 6 }, { 3, 4, 5, 6, 7 } };
  print(arr, 3, 5);//传入二维数组名,即二维数组首元素地址,即二维数组第一行的地址
  return 0;
}

在这里我们打印一个三行五列的二维数组。传参时我们传入二维数组的数组名,明确打印的起始位置;传入行数和列数,明确打印的数据范围。

通过上面对&数组名和数组名的认识,我们知道了这里传入的数组名代表的是二维数组的首元素地址,而二维数组的首元素第一行的元素,即传入的是一维数组的地址,所以我们必须用数组指针进行接收。

打印时,通过表达式 * (*(p+i)+j ) 锁定打印目标。

数组参数与指针参数(传参)

一维数组

#include<stdio.h>
void test1(int arr[10])//数组接收
{}
void test1(int *arr)//指针接收
{}
void test2(int *arr[20])//数组接收
{}
void test2(int **arr)//指针接收
{}
int main()
{
  int arr1[10] = { 0 };//整型数组
  int *arr2[20] = { 0 };//整型指针数组
  test1(arr1);
  test2(arr2);
}

整型数组

当向函数传入整型数组的数组名时,我们有以下几种参数可供接收:

1.数组传参数组接收,我们传入的是整型数组,那我们就用整型数组接收。
2.传入的数组名本质上是数组首元素地址,所以我们可以用指针接收。
3.数组的元素类型是整型,我们接收整型元素的地址用int * 的指针即可。

整型指针数组

当向函数传入整型指针数组的数组名时,我们有以下几种参数可供接收:

1.数组传参数组接收,我们传入的是整型指针数组,那我们就用整型指针数组接收。
2.指针接收,数组的元素是int * 类型的,我们接收int * 类型元素的地址用二级指针int ** 即可。

注意:一维数组传参,函数形参设计时[ ]内的数字可省略

二维数组

#include<stdio.h>
void test(int arr[][5])//数组接收
{}
void test(int(*arr)[5])//指针接收
{}
int main()
{
  int arr[3][5] = { 0 };//二维数组
  test(arr);
}

当向函数传入二维数组的数组名时,我们有以下几种参数可供接收:

1.二维数组传参二维数组接收。
2.指针接收,二维数组的首元素是二维数组第一行的地址,即一维数组的地址,我们用数组指针接收即可。

注意:二维数组传参,函数形参的设计只能省略第一个[ ]内的数字。

一级指针

#include<stdio.h>
void print(int* p, int sz)//一级指针接收
{
  int i = 0;
  for (i = 0; i < sz; i++)
  {
    printf("%d ", *(p + i));
  }
}
int main()
{
  int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  int sz = sizeof(arr) / sizeof(arr[0]);
  int* p = arr;//一级指针
  print(p, sz);
  return 0;
}

当我们传入的参数为一级指针时,我们可以用一级指针的形参对其进行接收,那么当函数形参为一级指针的时候,传入什么样的参数,具体看下面代码:

#include<stdio.h>
void test(int* p)
{}
int main()
{
  int a = 10;
  test(&a);//可以传入变量的地址
  int* p = &a;
  test(p);//可以传入一级指针
  int arr[10] = { 0 };
  test(arr);//可以传入一维数组名
  //...
  return 0;
}

总结:只要传入的表达式最终的类型是一级指针类型即可传入。

二级指针

#include<stdio.h>
void test(int** p)//二级指针接收
{}
int main()
{
  int a = 10;
  int* pa = &a;
  int** paa = &pa;
  test(paa);//二级指针
  return 0;
}

当我们传入的参数为二级指针时,我们可以用二级指针的形参对其进行接收,那么当函数形参为二级指针的时候,可以传入什么样的参数具体看下面代码:

#include<stdio.h>
void test(int** p)
{}
int main()
{
  int a = 10;
  int* pa = &a;
  test(&pa);//可以传入一级指针的地址
  int** paa = &pa;
  test(paa);//可以传入二级指针
  int* arr[10];
  test(arr);//可以传入一级指针数组的数组名
  //...
  return 0;
}

总结:只要传入的表达式最终的类型是二级指针类型即可传入。

总结:

相关文章
|
2天前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
8 1
|
24天前
链表指针的传参,传值和传地址
本文讨论了链表操作中指针传参的问题,特别是指针的传值与传地址的区别,并提供了修正代码,以确保链表插入操作能正确地修改指针指向的地址。
12 1
链表指针的传参,传值和传地址
|
11天前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
11天前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。
|
11天前
|
存储 算法 C语言
C语言:什么是指针数组,它有什么用
指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
|
17天前
魔法指针 之 二级指针 指针数组
魔法指针 之 二级指针 指针数组
15 1
|
20天前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
16 0
|
26天前
|
编译器 C语言
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
【C语言】指针篇-深入探索数组名和指针数组- 必读指南(2/5)
|
20天前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
19 0
|
2月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。