C语言指针就应该这么学 - 指针的进阶篇 上

简介: C语言指针就应该这么学 - 指针的进阶篇

文章目录

前言

💨 在C语言初识篇我们大概的对指针有了一些简单认识和概念。在正式对指针进阶的学习之前,先简单回忆下:

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

一、字符指针

1、什么是字符指针

💨 顾名思义就是指向字符的指针

int main()

{

  char ch = ‘q’;

  char* pc = &ch;

  return 0;

}

💨 当然也可以指向字符串

int main()

{

  //这里的字符串占了10个字节的空间,指针大小最大也就8个字节,怎么可能存的下。其实这里存储的是字符串的首元素的地址

  char* pc = “hello bit”;

  //不防一验:(对pc进行解引用,并输出。如果输出’h’则证实指针存储的是字符串的首元素地址)

  printf("%c\n", *pc);

  //相对于数组,字符串会被全部存储于内存中

  char arr[] = “hello bit”

  //当采用指针变量和数组首地址来输出字符串时,两者很相似

  printf("%s\n", ps);

  printf("%s\n", arr);

  return 0;

}

💨 常量字符串

2、 字符指针实例1:(出自《剑指offer》)

#include<stdio.h>
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;
}

输出结果:

分析:

两者都是对地址的比较

前者:对于数组来说要开辟两块不同的内存空间

所以地址当然不相同

后者:对于一个指向一个字符串的指针来说,这个字符串是常量不能被修改(因为不能修改,所以在内存里也没有同时存在2份及以上的必要)

因为str3和str4同时指向同一块空间,所以它们的地址是相同的

二、指针数组

1、什么是指针数组

💨 整型数组存放整型,字符数组存放字符。顾名思义指针数组就是一个存放指针的数组

int* arr[3];

arr数组里有3个元素,每个元素是int*类型的

2、怎么用

💨 这里介绍两种写法

#include<stdio.h>
//这种写法比较少见,没有什么应用场景:
int main01()
{
  int a = 10;
  int b = 20;
  int c = 30;
  int* arr[3] = {&a, &b, &c};
  int i = 0;
  for(i = 0; i < 3; i++)
  {
    printf("%d ", *(arr[i]));
  }
  return 0;
}
//常见的写法:
int main()
{
  int a[5] = {1, 2, 3, 4, 5};
  int b[5] = {2, 3, 4, 5, 6};
  int c[5] = {3, 4, 5, 6, 7};
  int* arr[3] = {a, b, c};
  //通过arr把a、b、c三个数组的内容输出
  int i = 0;
  for(i = 0; i < 3; i++)
  {
    int j = 0;
    for(j = 0; j < 5; j++)
    {
      //printf("%d ", *(arr[i] + j));
      printf("%d ", arr[i][j]);//同上
    } 
    printf("\n");
  }
}

三、数组指针

1、什么是数组指针

整型指针 -> 是指向整型的指针

字符指针 -> 是指向字符的指针

数组指针 -> 是指向数组的指针

int main()
{
  int a = 10;
  int* pa = &a;
  //----------------分割线----------------
  char ch = 'w';
  char* pc = &ch;
  //----------------分割线----------------
  int arr[10] = {1,2,3,4,5};
  int (*parr)[10] = &arr;
  //*parr是数组指针,指向10个整型元素的数组;parr的类型:把parr去掉int(*)[10]就是parr的类型
  return 0;
}

2、小例1:

💨 定义一个指针数组double* d[5] -> d是一个数组,有5个double*类型的元素,现将数组d存储

double*  (*pd) [5] = &d;

pd是一个数组指针,指向一个5个double *类型元素的数组

3、数组名

💨 我们都知道数组名有2种特殊用法:其1,sizeof(数组名)表示求整个数组的大小;其2,&数组名表示取整个数组的地址

int arr[10] = {0};

int* p1 = arr;

int (*p2)[10] = &arr;

#include<stdio.h>
int main()
{
  int arr[10] = {0};
  int* p1 = arr; //把数组首元素地址存储于p1,p1的类型是int*
  int (*p2)[10] = &arr; //这里的p2就是指向数组的指针,这个数组有10个元素,每个元素的类型是int;也可以说指针p2的类型是int[10]
  //p1和p2是相同的指向同一位置
  printf("%p\n", p1);
  printf("%p\n", p2);
  //但是p1和p2的类型不一样,它们的意义也不一样
  printf("%p\n", p1 + 1);//跳过一个整型
  printf("%p\n", p2 + 2);//跳过一个数组
  return 0;
}

4、数组指针的使用

💨 一般不会在一维数组上使用

#include<stdio.h>
int main()
{
  int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  int (*parr)[10] = &arr;
  int i = 0;
  for(i = 0; i < 10; i++)
  {
    printf("%d ", *((*parr) + i));//*parr相当于arr,
  }
  return 0;
}

💨 通常是在二维数组上使用

#include<stdio.h>
void print1(int arr[3][5], int r, int c)
{
  int i = 0;
  int j = 0;
  for(i = 0; i < r; i++)
  {
    for( j = 0; j < c; j++)
    {
      printf("%d ", arr[i][j]);
    }
    printf("\n");
  }
}
void print2(int(*p)[5], int r, int c)//二维数组传首地址同arr[0],这里使用数组指针来接收
{
  int i = 0;
  int j = 0;
  for(i = 0; i < r; i++)
  {
    for(j = 0; j < c; 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}};
  print1(arr, 3, 5);//通常方法
  printf("------------分割线------------\n");
  print2(arr, 3, 5);//数组指针
  return 0;
}

5、简单梳理

👁‍🗨 相信看到这里,可能许多小伙伴都会懵圈了

int arr[5]; -> arr是一个整型数组,可存储5个int类型的元素

int* parr1[10]; -> parr1是一个指针数组,可存储10个int*类型的元素

int (*parr2) [10]; -> prr2是一个数组指针,指向一个10个int类型的数组

int (*parr3[10]) [5]; -> parr3是一个数组,可存储10个int( * )[5] —— (数组指针)类型的元素,且每个数组指针指向一个5个int类型的数组


相关文章
|
7月前
|
存储 人工智能 Java
一文轻松拿捏C语言的指针的基础使用
本文介绍了C语言中的指针概念,包括直接访问和间接访问内存的方式、指针变量的定义与使用、取址运算符`&`和取值运算符`*`的应用,帮助读者深入理解指针这一C语言的核心概念。君志所向,一往无前!
136 0
|
9月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
300 7
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
9月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
1102 9
|
9月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
265 7
|
10月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
10月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
10月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
596 3
|
10月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
10月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
10月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
196 1