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语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下
|
9天前
|
存储 C语言
【C语言初阶】指针篇—上
【C语言初阶】指针篇—上
|
20天前
|
搜索推荐 程序员 C语言
指针赋值与引用传递:C语言的基础知识与实践技巧
指针赋值与引用传递:C语言的基础知识与实践技巧
|
18天前
|
搜索推荐 程序员 C语言
指针赋值与引用传递:C语言的基础知识与实践技巧
指针赋值与引用传递:C语言的基础知识与实践技巧
|
22天前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
22 0
|
23天前
|
C语言
C语言中的函数指针、指针函数与函数回调
C语言中的函数指针、指针函数与函数回调
12 0
|
1天前
|
存储 缓存 C语言
【C语言】字符函数,字符串函数,内存函数
C语言中的字符串函数和内存函数
8 0
【C语言】字符函数,字符串函数,内存函数
|
7天前
|
C语言
C语言5 字符输出函数和格式输出函数
C语言5 字符输出函数和格式输出函数
13 1
|
9天前
|
算法 编译器 C语言
深入浅出C语言—【函数】下
深入浅出C语言—【函数】下