指针中容易混淆的概念以及常见笔试题(代码片段)

不倒翁* 不倒翁*     2022-12-10     304

关键词:

C语言指针

文章目录

1.字符串指针

注:注意代码中的注释

  • : void* 类型的指针可以接收任意类型的指针
    - void 类型的指针不能进行解引用的操作,也不能进行加减整数的操作*
int main()

    char arr1[]="abcdef";
    char arr2[]="abcdef";
    char* p1="abcdef"; //常量字符串 不能修改
    char* p2="abcdef";
    if(arr1==arr2)  //arr相当于数组首地址 所以不相等
    
        printf("相等\\n");
    else
    
        printf("不相等\\n");
    
    
     if(p1==p2)  //指针里面放的常量字符串 ,所以相等
    
        printf("相等\\n");
    else
    
        printf("不相等\\n");
    

2.指针数组

指针数组是数组,存放指针的数组

int main()

    int arr1[]=1,2,3,4,5;
    int arr2[]=2,3,4,5,6;
    int arr3[]=3,4,5,6,7;
    int* parr[]=arr1,arr2,arr3;
    int i=0,j=0;
    for(i=0;i<3;i++)
    
        for(j=0;j<5;j++)
        
            printf("%d ",*(parr[i]+j))
        
        printf("\\n");
    
    return 0;

打印结果为:
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7    

3.数组指针

数组指针—指向数组的指针—存放数组的地址

int* p1[10]; 指针数组

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

arr表示的是数组首元素的地址

&arr表示的是数组的地址,而不是数组首元素的地址

int mian()

    char* arr[5];
    char* (*p)[5]=&arr;  //&arr取出的是一个数组的地址
      
    return 0;

int main()

    int arr[5]=1,2,3,4,5;
    int (*p)[5]=&arr;
    int i=0;
   // for(i=0;i<5;i++)
    //
      //  printf("%d ",*(*p+i)); //*p=arr 
   // 
    //或者下面这种写法
    for(i=0;i<5;i++)
    
        printf("%d ",(*p)[i]); //打印出1,2,3,4,5
    
    return 0;

#include <stdio.h>
void print1(int arr[3][5],int x,int y)

    int i,j;
    for(i=0;i<x;i++)
    
        for(j=0;j<y;j++)
        
            printf("%d ",arr[i][j]);
        
        printf("\\n");
    
    


void print2(int (*p)[5],int x ,int y)

    int i,j;
    for(i=0;i<x;i++)
    
        for(j=0;j<y;j++)
        
            printf("%d ",*(*(p+i)+j));  //*(p+i)代表每行首元素的地址
        
        printf("\\n");
    

int main()

    int arr[3][5]=1,2,3,4,5, 2,3,4,5,6, 9,3,4,5,6;
    print1(arr,3,5);
    print2(arr,3,5); //传的是一维数组的地址
    //数组名arr代表首原素的地址
    //但是二维数组的首元素是二维数组的第一行,所以这里传递arr,其实相当于第一行的地址,是一维数组的地址,可以用数组指针来接收
    
    return 0  

下面看看几种常见的写法:

int arr[5]; //arr是一个5个元素的整形数组
int* parr1[10]; //parr是一个数组,数组有10个元素,每个元素的类型是int*,parr1是指针数组
int (*parr2)[10]; //parr2是一个数组,数组有10个元素,每个元素的类型是int, parr2是数组指针
int (*parr3[10])[5]; //parr3是一个数组,该数组有10个元素,每个元素是一个数组指针,该数组指针指向的数组有5个元素,每个元素是int.

4.数组参数,指针参数

二维数组传参可以省略行,但不能省略列.

二级指针传参可以传哪些参数: 如下代码中的三种都行

void test(char **p)

 

int main()

 char c = 'b';
 char*pc = &c;
 char**ppc = &pc;
 char* arr[10];
 test(&pc);
 test(ppc);
 test(arr);//Ok?
 return 0;

5.函数指针 - 指向函数的指针

函数指针 - 指向函数的指针----存放函数地址的指针

int Add(int x ,int y)

    int z = x+y;
    return z;
    

int main()

    int a = 10 ;
    int b = 20 ;
    //&函数名和函数名都是函数的地址
    int (*p)(int, int)=Add;// 把add的地址传给了p
    printf("%d\\n", (*p)(2,3));//5
    printf("%d\\n",p(2,3)); //5
    //*可以加也可以不加
    return 0;

void (* signal(int ,void(*)(int)))(int) (1)
   
typedef void(*pfun)(int);  (2)
pfun signal(int , pfun)    (3)
    (2)(3)等效为(1)

6.函数指针数组

int Add(int x ,int y)

    return x + y ;

int Sub(int x , int y)

    return x - y;

int Mul(int x ,int y)

    return x * y;

int Div (int x , int y)

    return x/y ;

int main()

    int i = 0;
    //下面这个函数指针数组可以存放4个函数的地址
    int (*parr[4])(int , int ) = Add , Sub , Mul , div
   for(i=0;i<4;i++)
   
       printf("%d\\n",parr[i](2,3)); //5 -1 6 0
   
    return 0;

//char* my_strcpy(char* dest , const char* src)
//1.写一个函数指针pf,能够指向my_strcpy
char* (*pf)(char* , const char*)
//2.写一个函数指针数组,能够存放4个my_strcpy函数的地址
char* (*fp[4])(char* , const char*)

函数指针数组的用途 : 转移表

int Add(int x ,int y)

    return x + y ;

int Sub(int x , int y)

    return x - y;

int Mul(int x ,int y)

    return x * y;

int Div (int x , int y)

    return x/y ;

void meun()

    printf("**********************\\n");
    printf("**** 1.Add  2.Sub ****\\n");
    printf("**** 3.Mul  4.Div ****\\n");
    printf("****** 0.exit ********\\n");
    printf("**********************\\n");

int main()

    int x =0 ,y=0;
    int input = 0;
    meun();
    printf("请选择哪种算法\\n:");
    scanf("%d",&input);
    printf("请输入两个数:> ");
    scanf("%d%d",&x , &y);
    int (*parr[5])(int ,int )=0,Add,Sub,Mul,Div;
    do
    
        if(input>=1&&input<=4)
        
            printf("%d\\n",parr[inpnt](x,y));
        else if(input==0)
        
            printf("退出\\n");
        else 
        
            printf("选择错误\\n");
        
    while(input)
        return 0;

//注: 这题也可以用swich case ,但代码长度较长

小结

int Add(int x , int y)

    return x+y;

int main()

    //指针数组
    int* parr[4];
    //数组指针
    int* (*P)[4]=&parr;
   // 函数指针
    int (*p)(int ,int )=Add;
    //函数指针的数组
    int (*parr[4])(int , int)=Add,Sub,Mul,Div;
    //指向函数指针的数组的指针
      int (*(*parr)[4])(int , int);  

  • 回调函数: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针作为参数传递给另一个函数,当这个指针被用来调用其他所指向的函数时,我们就是说这是一个回调函数.回调函数不是由该函数的现实方直接调用,而是在特定的事件或条件发生时有另一方调用的,由于对该事件或条件进行响应. 如 :

    void cola (int (*fp)(int ,int))

    cola(Add);
    //cola 函数能Add函数的地址

    void print(char* str)
    
      printf("%s",str)  ;
        
    
    
    void test(void(*p)(char *))
    
        printf("TEST ");
        p("hello world");
    
    int main()
    
        test(print); //输出:TEST hello world
        return 0 ;
    
        
    

7.库函数qsort的用法: qsort(void* p,int num1 , int num2 , int (cmp)(counst void e1, counst void* e2) )

第一个参数 : 待排序数组首元素的首地址

第二个参数 : 待排序数组元素的个数

第三个参数 : 待排序数组每个数组元素的大小—单位为字节

第四个参数 : 函数指针–比较两个元素函数的地址,这个函数要自己实现

//自己实现一个qsort排序
struct stu

  char name[10];
  int age;
;
void swap(char *p1 ,char *p2, int witdh)

    int i= 0;
    for(i=0;i<witdh;i++)
    
     char temp=*p1;
        *p1=*p2;
        *p2=temp;
        p1++;
        p2++;
    
    


void bubble_sort(void* base, int sz ,int width , int (*cmp)(void *e1, void *e2))

    int i=0;
    //趟数
    for(i=0;i<sz-1;i++)
    
        int j=0 ;
        //每一趟比较的对数
        for(j=0;j<sz-1-i;j++)
        
            //两个元素的比较 得到两个元素的首地址
            if( cmp((char*)base+j*width , (char*)base+(j+1)*width ) >0 )
            
                //交换
                swap((char*)base+j*width , (char*)base+(j+1)*width ,width);
            
                
        
        
    
    

 
int cmp_init(void* p1,void* p2)

    return *(int*)p1-*(int*)p2;


void test1()

    int i=0;
     int arr[]=9,8,7,6,5,4,3,2,1,0;
    int sz=sizeof(arr)/sizeof(arr[0]);
    bubble_sort(arr,sz,sizeof(arr[0]),cmp_init);
    for(i=0;i<sz;i++)
    
        printf("%d",arr[i]);动态内存管理详解(动态内存函数介绍+常见动态内存错误+经典笔试题)(代码片段)

...c和free函数calloc函数realloc函数常见的动态内存错误1.对NULL指针的解引用操作2.对动态开辟空间的越界访问3.对非动态开辟内存使用free释放4.使用free释放一块动态开辟内存的一部分5.对同一块动态内存多次释放6.动态开辟内存忘记释... 查看详情

指针进阶—指针和数组笔试题解析[建议收藏](代码片段)

目录写在前面指针笔试题笔试题1笔试题2笔试题3笔试题4笔试题5笔试题6笔试题7笔试题8总结写在前面上一篇博客我已经为大家讲解了数组内容,大家可以先参照上一篇博客——指针进阶—指针和数组笔试题解析[建议收藏]࿰... 查看详情

字节跳动笔试题:链表反转(代码片段)

...:从反转一个链表说起 1.1:思路 链表作为一种以指针联系的数据结构,无法像数组一样进行某个元素的随机访问。在解决链表的问题上,我们唯一的法宝就是指针,通过定义不同的指针互相指引来改变聊表的顺序来解决... 查看详情

指针进阶—指针和数组笔试题解析[建议收藏](代码片段)

目录写在前面指针和数组笔试题解析知识普及-数组名的意义一维数组之sizeof笔试题字符数组1sizeof笔试题strlen笔试题字符数组2sizeof笔试题strlen笔试题常量字符串sizeof笔试题strlen笔试题二维数组普及小知识二维数组笔试题总结写在... 查看详情

小年糕后台笔试题(代码片段)

...,概率统计,unix进程通信,ip地址,静态变量,c语言的指针异常,以及一道编程题。 1.已知一棵二叉树,如果先序遍历的节点顺序是:ADCEFGHB,中序遍历是:CDFEGHAB,则后序遍历结果为:(D)A.CFHGEBDAB.CDFEGHBAC.FGHCDEBAD.CFHGEDBA把... 查看详情

[11道链表经典笔试题]优化的算法思想:反转链表链表相交快慢指针(代码片段)

1.删除链表中等于给定值val的所有节点AC代码/***Definitionforsingly-linkedlist.*structListNode*intval;*structListNode*next;*;*/structListNode*removeElements(structListNode*head,intval)structListNode*prev=NULL,*cur=head;w 查看详情

深入理解c指针经典笔试题——指针和数组(代码片段)

...专栏:【C语言】进阶部分🔹本文概括:一些指针和数组笔试题的解析 。🔹本文作者:花香碟自来_ 🔹发布时间:2023.3.12目录一、指针和数组练习题1.一维数组2.字符数组3.二维数组二、指针笔试题1.... 查看详情

大厂指针笔试题(1码+1图)详解——程序结果判断题(代码片段)

C指针相关系列1.一篇就够了(建议收藏)——超详解sizeof与strlen的用法2.C语言之深入指针进阶(建议收藏以备不时之需)3.回炉重造的C之指针+结构体大厂指针笔试题详解(1码+1图)——程序结果判断题... 查看详情

动态内存函数+经典笔试题@动态内存管理---malloc+free+calloc+realloc(代码片段)

...2.常见动态内存错误2.1对动态开辟的空间越界访问2.2对NULL指针解引用2.3对非动态开辟的内存用free释放2.4使用free释放动态开辟内存的一部分2.5对同一块内存多次释放2.6动态开辟的内存忘记释放(内存泄漏)3.经典笔试题3.1笔试题13. 查看详情

笔试题—2017网易有道(代码片段)

1、[编程题]洗牌洗牌在生活中十分常见,现在需要写一个程序模拟洗牌的过程。现在需要洗2n张牌,从上到下依次是第1张,第2张,第3张一直到第2n张。首先,我们把这2n张牌分成两堆,左手拿着第1张到第n张(上半堆),右手拿... 查看详情

c语言指针容易混淆的一些应用(代码片段)

数组名称等价于指针intiArry[]=1,2,3,4,5;int*p;p=iArry;//数组名iArry等价于一个指向该数组的指针//方括号[]数组下标运算符号相当于取址//怎么理解呢,iArry[1]等价于&iArry+1或*p+1;//数组名iArry是指向该数组第一个元素的... 查看详情

关于面试总结4-python笔试题(代码片段)

...。主要是给你一张纸和笔,让你现场写出来,那就没那么容易了。(本篇代码都是基于python3.6)1.统计统计在一个队列中的数字,有多少个正数,多少个负数,如[1,3,5,7,0,-1,-9,-4,- 查看详情

前端笔试题总结(代码片段)

选择题:1.jqueryajax中都支持哪些数据类型?text, html, xml, json, jsonp,and script.2.常见的浏览器端的存储技术有哪些?浏览器端:cookie、WebStorage(localStorage、sessionStorage)、userData、indexedDB服务器端:session 3. 查看详情

c语言篇+指针进阶练习+qsort模拟实现(回调函数思想)+指针和数组笔试题(代码片段)

...录前言冒泡排序了解qsortc语言库qsort的使用qsort模拟实现指针和数组笔试题解析一维数组字符数组二维数组总结:数组名的意义前言qsort(quicksort)根据你给的比较函数给一个数组快速排序,是通过指针移动实现排... 查看详情

一道头条笔试题:求区间的个数(代码片段)

...小的区间上[l,r]必然也满足上述条件,所以就可以用一个指针不停往后走。importjava.util.Scanner;publicclassMainMain()Sca 查看详情

二分图判断-笔试题(代码片段)

...能最多用两种颜色进行染色。题目保证没有重边和自环。概念:把相邻顶点染成不同颜色的问题叫做图的着色问题。对图进行染色所需要的最小颜色数称为最小着色度。最小着色度为2的图称作二分图。分析:如果只用两种颜色... 查看详情

c语言之动态内存管理(动态内存分配+经典笔试题+柔性数组)[建议收藏](代码片段)

...理相关知识。其中主要包括如何进行动态内存管理、一些常见的动态内存错误及柔性数组的介绍。❤️博主码云gitee链接:https://gitee.com/byte-binxin❤️文章目录为什么存在动态内存分配动态内存管理malloc和freecallocrealloc常见的... 查看详情

编辑和剪绳子-头条2019笔试题(代码片段)

...除操作时间复杂度(O(n)),会超时、超时、超时。考点:双指针算法importjava.util.*;publicclassMainpublicstaticvoidmain(String[]args)Scannersc=newScanner(System.in);intn=sc.nextInt();whi 查看详情