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

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

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

字符数组与字符指针

可以用字符串常量来给字符型指针进行初始化。

int *str1 = "How are you !";
//此时字符指针指向的是一个字符串常量的首地址,即指向字符串的首地址。
 
int *str2[] = "How are you !";
//此时,str2是字符数组,它存放的是一个字符串。

字符指针str1与字符数组str2的区别是:


str1是一个变量,可以改变str1的值,即str1可以指向不同内存单元的地址。



指针字符数组的指针

定义一个字符指针指向字符数组后,就可以利用指针来处理该字符数组中存储的字符串。使用指针处理字符串,不仅书写方便,而且程序的运行效率更高。

用指针处理字符串的方法是:首先定义一个字符指针,然后将字符数组的首地址赋值给该指针。

例如:

char str[] = "Hello world !";
char *p = str;

看下面一段代码:

#include <stdio.h>
int main()
{
  char str[] = "Hello world !";
  char *p = str;     
  printf("%s\n", p);
  p += 6;
  printf("%s\n", p);
  return 0;
}


其运行结果为:

其中p初始化时存储了str的首地址,故打印出来了完整的字符串。

而后将指针p往后移了6位,使得其新的首地址从‘w’开始,所以打印出来的结果变成了“world!”。

指针与函数

 

函数型指针的定义

在C语言中,定义了函数之后,系统为该函数分配一段连续的存储空间。其中函数的起始地址称为该函数的入口地址,将此地址赋给另外一个变量,则该变量为一个指向函数的指针。

指向函数的指针变量的一般形式为:

类型说明符(* 标识符)();

其中,类型说明符为被指针所指向的函数的返回值的数据类型;标识符为一个指针名(不是函数名),该指针只能指向函数;括号中为空,但括号必须有,表示该指针是专指函数的。

例如:

int (*p)();

函数型指针的赋值

用函数名为指针初始化,表示指针指向该函数。

例如:

int (*p)();   //定义函数型指针
int fun();    //声明函数fun
p = fun;      //让指针p指向函数fun

关于函数型指针的赋值说明:

(1)当函数型指针指向了某一函数后,此函数的调用可以用函数名,也可以用指针(用*p代替原函数名);

(2)用函数型指针定义之后,不是固定指向某一个函数,而是先后指向不同的函数(给它赋值其他入口地址即可改变其指向的函数);

(3)为函数型指针赋值时,不必用参数;

(4)对指向函数的指针变量,先p + n,p ++,p -- 等运算是没有意义的。

指针型函数的定义与使用

调用函数,通常得到一个返回值带回主调函数。如果返回值为一个指针时,则该函数就是指针型函数。

定义形式:

类型说明符  *标识符(形参列表);

例如:

int *a(int x,int y);

其中a是函数名,调用它以后能得到一个指向整型数据的指针。x、y是函数a的形参,为整型。因此,指针型函数也就是返回指针值的函数。

 

利用指针型函数,求一个二维数组中的最大值,并返回它的地址

#include <stdio.h>
#define ROW 3   //宏定义二维数组的行和列
#define COL 4
 
int* max(int a[ROW][COL])
{
  int *p, i, j;
  p = a[0];
  for (i = 0; i < ROW; i++)
  {
    for (j = 0; j < COL; j++)
    {
      //判断大小
      if (*p < *(*(a + i) + j))
        p = *(a + i) + j;
    }
  }
  return p;
}
 
int main()
{
  int a[ROW][COL], i, j, * p;
  printf("请输入二维数组值:");
  for (i = 0; i < ROW; i++)
  {
    for (j = 0; j < COL; j++)
    {
      scanf("%d", &a[i][j]);
    }
  }
  //将二维数组传参进函数a
  p = max(a);
  for (i = 0; i < ROW; i++)
  {
    for (j = 0; j < COL; j++)
    {
      printf("%d\t", a[i][j]);
    }
    printf("\n");
  }
  printf("最大值为:%d\n", *p);
  return 0;
}

其运行结果为:

 

指针数组

由若干个指针变量组成的数组,称为指针数组。指针数组也是数组的一种,所有有关数组的概念都适用它。但指针数组与普通数组又有区别,指针数组的数组元素是指针类型的,只能用来存放地址值。

指针数组的定义

定义形式:

类型说明符  *数组名[数组长度];

例如:

int *p[4];

这条语句定义了一个指针数组p,该数组中有4个元素,每个元素都是一个指针,指向int型数据。指针数组比较适合用来指向若干个字符串,使字符串处理更加方便灵活。


值得注意的是:


指针数组语句:int *p[ 4 ];符号[]的优先级比符号*高,因此变量名p先与[]结合,表示这是一个长度为4的数组;再与*和int结合,表示该数组的元素的数据类型是int * 型,每个数组元素都可以指向一个整型变量。  

指针数组的初始化

指针数组是由若干个指针变量组成的数组,因此必须用地址值为指针数组初始化。

例如:

int arr[3][3] = {1,2,3,4,5,6,7,8,9};
 
int *pa[3] = {arr[0],arr[1],arr[2]};

由于arr是一个二维数组,所以arr[ 0 ],arr[ 1 ],arr[ 2 ]为该二维数组的每一行的首地址。

故而,可以通过指针数组来引用二维数组中的元素:

pa[i] + j = arr[i] + j = &arr[i][j];
 
*(pa[i] + j) = *(arr[i] + j) = arr[i][j]; 

用字符指针数组表示一组字符串,即每个数组元素分别指向一个字符串,然后进行字符串的比较:

 

#include <stdio.h>
#include <string.h>
int main()
{
  char *s[4] = { "hello","Circle","Square","Rectangle" };
  char *temp;
  int i, j, k;
  for (i = 0; i < 4; i++)
  {
    printf("%d:%s\n", i + 1, s[i]);  //按原始顺序输出4个字符串
  }
  for (i = 0; i < 3; i++)
  {
    //使得前一个字符串与后面几个字符串对比
    k = i;
    for (j = i + 1; j < 4; j++)
    {
      if (strcmp(s[k], s[j]) > 0)
        k = j;
      if (k != i)
      {
        temp = s[i];
        s[i] = s[k];
        s[k] = temp;       //交换指针指向的字符串
      }
    }
        
  }
  printf("\n");
  for (i = 0; i < 4; i++)
  {
    printf("%d:%s\n", i + 1, s[i]);   //输出排序后的4个字符串
  }
  return 0;
}

其运行结果为:

 

多级指针

如果一个指针变量存放的是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量,即多级指针(指向指针的指针)

多级指针定义的一般形式如下:

类型说明符  * * 指针名;

例如:

int x = 4;
int *p ;
int **p ;
p = &x;   //指针变量p指向整型变量x
q = &p;   //二级指针q指向指针变量p

看下面代码:

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

其运行结果为:

所以说,以上三种方式都是等价的。

要注意的:指向指针的指针是间接地指向目标变量,因此,将直接指向目标变量的指针称为一级指针,将指向指针的指针称为二级指针,将指向二级指针的指针称为三级指针,以此类推。

通过指向指针的指针输出数组元素:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
  srand((unsigned int)time(NULL));
  int arr[5][3],a,b,**p;
  int *num[5] = { arr[0],arr[1],arr[2],arr[3],arr[4] }; //指针数组
  p = num;  //指向指针数组的指针
  for (a = 0; a < 5; a++)   //随机初始化二维数组
  {
    for (b = 0; b < 3; b++)
    {
      arr[a][b] = rand() % 20 + 1;
    }
  }
 
  for (a = 0; a < 5; a++)   
  {
    for (b = 0; b < 3; b++)
    {
      printf("%2d\t", *(*p + b));  //通过二级指针输出数组元素
    }
    printf("\n");
    p++;
  }
  return 0;
}

其运行结果为:

目录
相关文章
|
9月前
|
存储 人工智能 程序员
一文彻底搞清楚C语言的数据类型和变量
本文介绍了数据类型(基本、构造、指针、空类型)、变量(使用、命名规则、作用域)和常量(字面、符号、枚举、表达式),帮助初学者理解编程基础概念。坚持学习,定能创造奇迹!
1640 1
一文彻底搞清楚C语言的数据类型和变量
|
11月前
|
存储 编译器 C语言
【C语言】C语言的变量和声明系统性讲解
在C语言中,声明和定义是两个关键概念,分别用于告知编译器变量或函数的存在(声明)和实际创建及分配内存(定义)。声明可以多次出现,而定义只能有一次。声明通常位于头文件中,定义则在源文件中。通过合理组织头文件和源文件,可以提高代码的模块化和可维护性。示例包括全局变量、局部变量、函数、结构体、联合体、数组、字符串、枚举和指针的声明与定义。
422 12
|
11月前
|
C语言
【C语言】全局搜索变量却找不到定义?原来是因为宏!
使用条件编译和 `extern` 来管理全局变量的定义和声明是一种有效的技术,但应谨慎使用。在可能的情况下,应该优先考虑使用局部变量、函数参数和返回值、静态变量或者更高级的封装技术(如结构体和类)来减少全局变量的使用。
203 5
|
12月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
12月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
12月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
12月前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
1086 13
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
484 4
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
162 0