指针的进阶(1)

简介: 指针的进阶(1)

指针的回顾

在C语言中,指针是一个变量,与其他数据不同的是,它的作用是用来存储其它变量的内存地址。指针可以指向不同类型的数据,包括整数、浮点数

、字符、数组等。通过使用指针,我们可以直接访问和修改存储在内存中的数据,而不需要进行复制或者传递大量的数据。

这是指针的大概情况,下面就要对指针进一步研究。


字符指针

对于字符来说,我们可以用char类型来创建变量,那么就有char*类型的指针,通常我们称之为字符指针。

先看以下代码:

int main()
{
 char ch = 'w';
 char *pc = &ch;
 *pc = 'w';
 return 0;
}
创建一个字符变量ch,字符指针pc指向ch的地址,对pc解引用就是'w'。


这是常规的用法,但在大多数情况下,以下情况更加普遍使用:

int main()
{
 const char* pstr = "hello cc.";
 printf("%s\n", pstr);
 return 0;
}


在这里,打印出来的就是“hello cc",但pstr存的是字符串的首元素地址
,也就是说,对ptsr解引用,得到的是'h'。

在这里,会发现我在指针pstr加入了const,这是因为字符串的地址本来就不可改变,加上const,增加程序的可读性和维护性。看下面例子:

#include <stdio.h>
int main()
{
 char str1[] = "hello cc.";
 char str2[] = "hello cc.";
 const char *str3 = "hello cc.";
 const char *str4 = "hello cc.";
 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;
}


结果:

对于str1和str2,它们是字符数组,对于数组来说,会在内存中开辟空间,而str1和str2是两个不同的字符数组,虽然它们的内容相同,但开辟的空间肯定是不一样的,而数组名一般又是指首元素的地址,所以各不相同;对于str3和str4,它们是字符指针,相当与常量字符串自己开辟了空间,然后两个指针都会指向内容相同的字符串首元素。


指针数组

顾名思义,它是一个数组,只是每个数组里面存放的是指针;

我们可以用指针数组实现二维数组

int main()
{
  int arr1[] = { 1,2,3,4,5 };//arr1 - int*
  int arr2[] = { 2,3,4,5,6 };
  int arr3[] = { 3,4,5,6,7 };
  //指针数组
  int* arr[3] = { arr1, arr2, arr3 };
  int i = 0;
  for (i = 0; i < 3; i++)
  {
    int j = 0;
    for (j = 0; j < 5; j++)
    {
      printf("%d ", arr[i][j]);
    }
    printf("\n");
  }
  return 0;
}


对于一维数组来说,本质上就是一维指针,也就是arr1 类型为int*.

数组指针

指针的定义

数组指针,是一个指针,指向数组的指针。

int *p1[10];//指针数组

int (*p2)[10];//数组指针


这里要注意:[]的优先级要高于号的,所以必须加上()来保证p先和结合。

&数组名VS数组名

int arr[10];


我们知道,arr是指首元素地址,&arr指的是整个数组的地址;

int main()
{
  int arr[10] = { 0 };
  printf("%p\n", arr);
  printf("%p\n", &arr[0]);
  printf("%p\n",&arr);
  return 0;
}


上面虽然的地址都是一样,这是因为刚好都指向了首元素地址

int main()
{
  int arr[10] = { 0 };
  printf("%p\n", arr);//
  printf("%p\n", arr+1);//
  printf("%p\n", &arr[0]);//
  printf("%p\n", &arr[0]+1);//
  printf("%p\n", &arr);//
  printf("%p\n", &arr+1);//
  return 0;
}


但我们把16进制转换为10进制后&arr+1就增加了40个bit,但arr+1相对于arr只增加了4bit

根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。

实际上: &arr 表示的是数组的地址,而不是数组首元素的地址.


数组指针的使用

直接看以下代码:

#include <stdio.h>
void print_arr1(int arr[3][5], int row, int col)
{
  int i = 0;
   for(i=0; i<row; i++)
  {
   for(j=0; j<col; j++)
   {
   printf("%d ", arr[i][j]);
   }
   printf("\n");
 }
}
void print_arr2(int (*arr)[5], int row, int col)
{
 int i = 0;
 for(i=0; i<row; i++)
 {
  for(j=0; j<col; j++)
  {
   printf("%d ", arr[i][j]);
  }
   printf("\n");
 }
}
int main()
{
   int arr[3][5] = {1,2,3,4,5,6,7,8,9,10};
   print_arr1(arr, 3, 5);
   print_arr2(arr, 3, 5);
   return 0;
}


对于一维数组来说,数组名表示首元素地址,而二维数组中,首元素表示的是第一行的地址,所以把数组指针看作是二维数组中,指向一维数组的指针。也就是所,二维数组可以由数组指针来表示。

数组参数、指针参数

一维数组传参

#include <stdio.h>
void test(int arr[])
{}
void test(int arr[10])
{}
void test(int *arr)
{}
void test2(int *arr[20])
{}
void test2(int **arr)
{}
int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0};
 test(arr);
 test2(arr2);
}


对于以上所有test函数来说,所有形式参数都是可以接收到实参的;数组本质来说就是指针,所以可由指针来接收;而指针数组来说,就要用二维指针来接收。

二维数组传参

void test(int arr[3][5])
{}
void test(int arr[][5])
{}
//对于二维数组来说,行的数字可以省略,列的数字不能省略
void test(int *arr)
{}
void test(int (*arr)[5])
{}
//数组指针是可以的,但对于指针数组来说,数组中包含的是指针,虽然说
//数组本质就是指针,但是由于数组的限制,指针的地址可能会出现连续的
//状态,无法确定一行中有多少列,故不可使用。


一级指针传参

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


对于数组来说,元素的地址是连续存在的,所以可以用指针叠加的方式进行循环遍历。

二级指针传参

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


num=10

num=10

对于实参来说,只要是一级指针的地址,就可以传参,而函数中的形参一般只用二级指针接收即可。

总的来说,对于数组传参,形参部分可以是指针,也可以是数组;
而对于指针传参,实参部分只要是地址,都可以当作实参,形参只用指针来接收。

相关文章
|
6月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
6月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
6月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
6月前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
6月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
6月前
|
搜索推荐
指针进阶(2)
指针进阶(2)
54 4
|
6月前
指针进阶(3)
指针进阶(3)
47 1
|
6月前
|
C++
指针进阶(1)
指针进阶(1)
47 1
|
6月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
52 2
|
7月前
|
C语言
C语言进阶:进阶指针(下)
C语言进阶:进阶指针(下)
51 2