c语言------指针(3)

目录

二级指针

指针数组 

指针数组模拟二维数组

 字符指针变量

数组指针变量

 数组传参

1、一维数组传参

2、二维数组传参

函数指针变量


二级指针

我们之前所见到的大部分为一级指针,如:

int * p;

char *p;

float *p;

double *p;

下面我们来了解一下,二级指针

int main()
{
    int a = 10;
    int* p = &a;//取出a的地址
    //p是指针变量,是一级指针
    int* * pp=&p;//pp是二级指针
    int** * ppp = &pp;//ppp是三级指针
}

指针数组 

 指针数组到底是数组还是指针?

类比一下:

整型数组------存放整型的数组(数组中每个元素是整型类型);

int p[10];

字符数组------存放字符的数组(数组中每个元素是字符类型);

char p[10];

指针数组------存放指针的数组(数组中每个元素是指针类型);

int *p[10];

所以,指针数组是一个数组

指针数组模拟二维数组

模拟出二维数组的效果,并不是二维数组!

int main()
{
    int arr1[] = { 1,2,3,4,5 };
    int arr2[] = { 2,3,4,5,6 };
    int arr3[] = { 3,4,5 ,6,7};

    int* arr[] = { arr1,arr2,arr3 };//指针模拟二维数组

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            printf("%d ", arr[i][j]);//     *(*(arr+i)+j)
        }
        printf("\n");
    }
}

 字符指针变量

    char c = "w";
    char* p = &c;//p就是字符指针

char* p = "abcedf";如何理解?

它并不是把abcedf\0,存放在p中,而是把第一个字符的地址存放在p中;

int main()
{

    char* p = "abcedf";
    printf("%c\n", *(p + 2));
    printf("%c\n", *(p+1));
    //1、可以把字符串想象成一个字符数组,但是这个数组不能修改
    printf("%c\n", "abcedf"[3]);
    printf("%c\n", p[3]);
    //2、当常量字符串出现在表达式中的时候,他的值是第一个字符的地址

}

深入理解:

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");
}

代码的打印结果是什么?

为什么会是这个结果?我们来调试一下。

str1和str2并未建立联系,二者是在不同的内存块中存放相同的值,是一个独立的个体;

而str3和str4的指向地址相同;

数组指针变量

 什么是数组指针变量?

还是和指针数组一样来类比一下:

整型指针(int *):指向整型的指针--->整型指针变量存放的是整型的地址;

字符指针(char *):指向字符的指针--->字符指针变量存放的是字符的地址;

数组指针:指向数组的指针--->数组指针变量存放的是数组的地址;

所以,数组指针是一个指针

下面代码哪一个是数组指针变量?

首先我们要知道 [] 的优先级高于 *

1、int *p1[10];

2、int *(p2)[10];

1、p1是数组,数组10个元素,每个元素是int *类型;

2、p2是指针,指针指向的是数组,数组有10个元素,每个元素是int类型;

所以p2是数组指针;

int main()
{
    int n = 100;
    int* pn = &n;

    char c = 'w';
    char* pc = &c;

    float f = 3.14f;
    float* pf = &f;

    int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
    int (*parr) [10] = &arr;//取出数组的地址
    //parr就是数组指针

}

 数组传参

1、一维数组传参

形参可以是数组,也可以是指针;

1、可以写出数组,更加直观;

2、可以写出指针,数组传参传递的是首元素的地址

一维数组传参本质上是传递首元素的地址;

int arr[10];

test(arr,10);

1、void test (int arr[],int sz) {}

2、void test (int *arr,int sz) {}

2、二维数组传参

形参可以写出数组,同样也可以写出指针的形式;

#include<stdio.h>
void Print1(int arr[3][5], int r, int c)
{
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}


void Print2(int (*arr)[5], int r, int c)
{
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			printf("%d ", *((*(arr+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);
	Print2(arr, 3, 5);
}

 二维数组的首元素的地址如何理解?

函数指针变量

我们知道:

数组名:数组首元素的地址

&数组名:整个数组的地址

函数名:函数的地址

&函数名:函数的地址

int Add(int x, int y)
{
    return x + y;
}
int main()
{
    //int a = 10;
    //int* pa = &a;//整型指针

    //int arr[10] = { 0 };
    //int (*parr)[10]= & arr;//数组指针

    //函数指针变量,用来存放函数的地址
    //printf("%p\n", &Add);
    //printf("%p\n", Add);

    int (*pf)(int,int) = &Add;//pf就是函数指针变量

    int ret = Add(3, 5);
    printf("%d\n", ret);

    int ret2 = (*pf)(2, 2);
    printf("%d\n", ret2);

    int ret3 = pf(5, 2);
    printf("%d\n", ret3);
}

举例:

理解下面两个代码:

int main()
{
    (*(void (*)())0)();
    return 0;
}

我们进行拆分一下:

先看:void(*)() :这是一个函数指针类型;

对于(int)3.14:这是强制类型转换;

那对于:(void(*)()) 0:也是如此,把0这个整数值强制类型转换成一个函数的地址;

(*(void(*)()) 0)():最后一层也是一个函数指针类型,返回值为void类型;

   void (*singal(int, void(*)(int)))(int);

int main()
{
    return 0;
}

和上面一样进行拆分:

signal是一个函数

signal函数的参数有2个,第一个是int类型

第二个是函数指针类型,该指针指向的函数参数是int,返回类型是void

signal函数的返回类型是这种类型的void(*)(int)函数指针

该指针指向的函数参数是int,返回类型是void

以上就是全部内容,希望有所帮助!

  • 32
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值