C语言指针进阶操作 - 指针类型|指针传参|回调函数|笔试题

目录

1指针的大小

2指针类型

2.1字符指针

2.1.1指向字符串常量

2.1.2指向字符数组

2.1.3访问字符串

2.1.4使用指针遍历字符串

2.2指针数组

2.3数组指针

2.4函数指针

2.4.1来看两段代码

2.4.1回调函数

2.5函数指针数组

3数组参数,指针参数

3.1&数组名 VS 数组名

3.2一维数组传参

3.3二维数组传参 

3.4一级指针传参

3.5二级指针传参

4指针笔试题

4.1对于数组名和字符串指针的理解  

4.2程序的结果是什么?

4.3如下表表达式的值分别为多少?

4.4程序的结果是什么?

4.5小心有坑!

4.6打印结果为?

4.7Work at alibaba


1指针的大小

指针是一种特殊的变量,用于存储内存地址。可以直接访问内存中的数据,而无需知道变量的名称。指针变量包含一个内存地址,该地址指向存储在计算机内存中的数据位置。

指针的大小即地址的大小,地址是物理的电线上产生的,对于32位机器,有32根地址线,即有32个1和0组成的二进制序列,这个二进制序列就叫做地址,需要32个比特位才能存储这个地址。许多32位操作系统上,指针通常是4个字节(32位),而在64位操作系统上,指针通常是8个字节(64位)。 

虽然指针的大小都是4/8字节,但指针仍有许多类型,不同类型对应的指针在存放、解引用、指针运算上有差异。

2指针类型

2.1字符指针

字符指针是指向字符数据的指针,在处理字符串和字符数组中有重要作用。

字符指针的用途包括但不仅限于:

2.1.1指向字符串常量

char *strPtr = "Hello, world!";

要注意,这里不是把一个字符串放到strPtr指针变量里了,本质是把字符串"Hello World"的首字符的地址放到了strPtr中。

有一道面试题考察了这个知识点:

#include <stdio.h>
int main()
{
    char str1[] = "hello world.";
    char str2[] = "hello world.";
    char *str3 = "hello world.";
    char *str4 = "hello world.";
    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 and str2 are not same
str3 and str4 are same

数组名是首地址,str1和str2的首地址不一样,所以str1和str2显然不相等;*str3和*str4都指向了同一个字符串,两个字符指针存放的地址是相同的,所以是str3和str4是相同的。 

2.1.2指向字符数组

char str[] = "Hello";
char *strPtr = str;

2.1.3访问字符串

printf("%s", strPtr);

2.1.4使用指针遍历字符串

while (*strPtr != '\0') {
    printf("%c", *strPtr);
    strPtr++;
}

字符指针在中经常用于字符串的处理和操作,例如字符串的拷贝、比较、连接等。这些功能包含在string.h中,详见:cplusplus.com/reference/cstring/?kw=string.h

2.2指针数组

指针数组,即存放指针的数组。数组的每一个元素都是一个指针类型的变量。示例如下:

int *p[10];

这里要注意: [] 的优先级要高于 的,所以 先与 [] 结合,说明他的一个存放10个变量的数组,而数组的每一个变量类型是 int*。

数组指针的使用:

指针数组的使用场景很多,其中一个典型的用法是处理字符串数组。比如:

#include <stdio.h>

int main() {
    char *strings[] = {"apple", "banana", "orange"};

    for (int i = 0; i < 3; i++) {
        printf("%s\n", strings[i]);
    }

    return 0;
}

还可以通过指针数组来模拟实现二维数组:

#include <stdio.h>

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[3] = { arr1, arr2, arr3 };

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

2.3数组指针

数组指针,即指向数组的指针。与指针数组不同,数组指针指向的是一个完整的数组,而不是数组中的单个元素。示例如下:

int (*p)[10];

由于 () 优先级最高,所以 p 先与 结合,说明他是一个指针,指向的是一个大小为10,元素类型为int的数组。

数组指针的一个重要运用就是传递多维数组给函数

#include<stdio.h>

void printArray(int (*arr)[3], int rows) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", arr[i][j]);
            //也可以写为:printf("%d ", *(*(arr + i) + j));
        }
        printf("\n");
    }
}

int main() {
    int arr[2][3] = {
  
  {1, 2, 3}, {4, 5, 6}};
    printArray(arr, 2);
    return 0;
}

二维数组的数组名表示二维数组第一行的地址,是一个一维数组的地址,类型为数组指针。所以这里 printArray 函数接收的是二维数组第一行的地址,通过arr[i][j]的方式来访问arr数组的第i行第j个元素。

2.4函数指针

函数指针可以用来存储函数的地址,使得可以动态地选择调用不同的函数,从而实现一些高级的编程技巧和模式。

若定义有:int add(int x, int y)
int (*p)(int int)  -->  就是函数指针变量

2.4.1来看两段代码

(*(void (*)())0)()

 从里层括号开始看:

  1. void(*)()是函数指针类型
  2. 括号里面放类型 就相当于 强制类型转换,相当于将0(地址处)强制
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值