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

花碟 花碟     2023-03-13     536

关键词:

 

🔹内容专栏:【C语言】进阶部分

🔹本文概括:一些指针和数组笔试题的解析 。

🔹本文作者:花香碟自来_ 

🔹发布时间:2023.3.12

目录

一、指针和数组练习题

1. 一维数组

2. 字符数组

3. 二维数组

二、 指针笔试题

1. 第一题

2. 第二题

3. 第三题

4. 第四题

5. 第五题

6. 第六题

7. 第七题

8. 第八题


          

一、指针和数组练习题

首先我们在练习此方面的题目前,回顾一下相关概念。

数组和指针

数组:能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型。

指针:地址or指针变量,指针的大小为4/8个字节(由CPU的寻址位数决定)

数组是数组,指针是指针,二者不等价。

数组名是数组首元素的地址,这个地址可以存放到指针变量当中。

可以根据指针来遍历数组的操作。


数组名

大部分情况下表示的是数组首元素的地址。

但是除了以下两个例外:

sizeof(数组名) ,此时的数组名表示的是整个数组,且单独存放在sizeof( )内部,计算的是整个数组大小;

&数组名,此时的数组名表示的是整个数组,取出的就是数组的地址。

sizeof与strlen

1.sizeof计算的是占用内存空间的大小,单位是字节,不会关注内存中到底存放的是什么;

2.sizeof不是函数,而是操作符;

3.strlen是函数;

4.strlen是针对字符串的,求的是字符串的长度,本质上统计的是'\\0'之前出现的字符的个数。

1. 一维数组

//一维数组
#include<stdio.h>
int main()

    int a[] = 1,2,3,4;
    printf("%d\\n",sizeof(a));//1
    printf("%d\\n",sizeof(a+0));//2
    printf("%d\\n",sizeof(*a));//3
    printf("%d\\n",sizeof(a+1));//4
    printf("%d\\n",sizeof(a[1]));//5
    printf("%d\\n",sizeof(&a));//6
    printf("%d\\n",sizeof(*&a));//7
    printf("%d\\n",sizeof(&a+1));//8
    printf("%d\\n",sizeof(&a[0]));//9
    printf("%d\\n",sizeof(&a[0]+1));//10
     return 0;

分析:

//1: 数组名单独放在sizeof()内部,计算的是数组总大小,单位是字节。16

//2: 此时的a并没有单独存放在sizeof()内部,a+0计算的就是数组首元素的地址,地址的大小是4/8个字节。

//3:此时的a没有单独存放在sizeof()内部,a表示数组首元素的地址(&a[0]),*a 就等价于*&a[0],等价于a[0],计算的是第一个元素类型的大小,结果是4

//4: a是数组首元素的地址,类型是int*,a + 1就是跳过一个整型的大小,得到的是第二个元素的地址,计算的就是第二个元素地址的大小,结果就是4/8字节

//5:a[1] 等价于 *(a + 1),计算的就是第二个元素的大小,结果是4

//6:&a表示的是取出整个数组的地址,结果计算的就是整个数组地址的大小,结果是4/8个字节

//7:(1)&a表示的是整个数组的地址,*星号解引用,拿到的就是整个数组,  *&a == a,sizeof(a)计算的就是整个数组的大小,结果是16

     (2)也可以看做是&a 放在一个指针中,这个指针的类型就是 int (*) [4],*解引用, 访问的就是一个数组的大小,数组有4个元素,每个元素是int类型,结果就是4 * 4 为16

//8:&a 表示的是整个数组的地址,类型是 int  (*)[4]  ,&a + 1跳过的就是一个数组的大小,

结果是4/8个字节

//9:a[0] 等价于*(a + 0),表示的就是第一个元素,&a[0]就是第一个元素的地址, 结果就是4/8个字节

//10:&a[0] + 1 ,即第一个元素的地址 + 1,得到的是第二个元素的地址,结果是4/8个字节

2. 字符数组

#include<stdio.h>
int main()

    char arr[] = 'a','b','c','d','e','f';
    printf("%d\\n", sizeof(arr)); //1
    printf("%d\\n", sizeof(arr+0));//2
    printf("%d\\n", sizeof(*arr));//3
    printf("%d\\n", sizeof(arr[1]));//4
    printf("%d\\n", sizeof(&arr));//5
    printf("%d\\n", sizeof(&arr+1));//6
    printf("%d\\n", sizeof(&arr[0]+1));//7

    printf("%d\\n", strlen(arr));//8
    printf("%d\\n", strlen(arr+0));//9
    printf("%d\\n", strlen(*arr));//10
    printf("%d\\n", strlen(arr[1]));//11
    printf("%d\\n", strlen(&arr));//12
    printf("%d\\n", strlen(&arr+1));//13
    printf("%d\\n", strlen(&arr[0]+1));//14
    return 0;

  //10 访问时冲突: 

    

         

 分析:

//1:  arr数组名单独存放在sizeof()内部,计算的是整个数组的大小,故结果是6

//2:  arr + 0 是数组首元素的地址,计算的是地址的大小,结果是4/8个字节。

//3: *arr,表示的是对数组首元素的地址进行解引用,拿到的就是首元素,计算的是数组首元素的大小,结果是1

//4:  arr[1],等价于*(arr + 1),对数组第二个元素的地址解引用,拿到第二个元素,计算的就是第二个元素的大小,结果是1

//5: &arr 表示的就是整个数组的地址,结果是4/8个字节

//6: &arr + 1 表示跳过一个数组的大小,但还是地址,结果还是4/8个字节

//7: &arr[0]表示的就是数组首元素的地址,&arr[0] + 1 跳过一个char类型的大小,结果还是4/8个字节。

//8: 此处的数组名代表的是数组首元素的地址,计算字符串长度,所以需要寻找'\\0'的位置,但是我们不确定'\\0'会出现在哪个位置,故而我们认为结果是个随机值

//9: arr + 0,还是表示的是数组首元素的地址,结果同上,依旧是一个随机值

//10: 这里的arr表示的就是数组首元素的地址,*arr拿到的是'a',但是传入strlen()的参数必须是一个指针,而这里的'a',实际把a的ASCII码值转换为指针的形式,然后访问,但是这个地址并不是“自己”的,所以形成了非法访问的情况。(观察上方图片,0x00000061就是97,即'a'的ASCII码值。)

//11:arr[1]表示的是数组的第二元素,传入strlen,会将'b'(98)当成地址,也会形成非法访问

//12: &arr表示取出整个数组的地址,数组的起始地址仍然指向'a',向后寻找'\\0',所以还是一个随机值

//13:&arr + 1跳过了一个数组的大小,仍然向后寻找'\\0',直到找到'\\0'结束,但它与前一条(//12)相比,会少数6次,故可以认为是随机值 - 6

//14:&arr[0] + 1是第二个元素的地址,即从指向'b'的位置开始向后数,可以认为是随机值 - 1


#inlude<stdio.h>
int main()

    char arr[] = "abcdef";
    printf("%d\\n", sizeof(arr));//1
    printf("%d\\n", sizeof(arr+0));//2
    printf("%d\\n", sizeof(*arr));//3
    printf("%d\\n", sizeof(arr[1]));//4
    printf("%d\\n", sizeof(&arr));//5
    printf("%d\\n", sizeof(&arr+1));//6
    printf("%d\\n", sizeof(&arr[0]+1));//7

    printf("%d\\n", strlen(arr));//8
    printf("%d\\n", strlen(arr+0));//9
    printf("%d\\n", strlen(*arr));//10
    printf("%d\\n", strlen(arr[1]));//11
    printf("%d\\n", strlen(&arr));//12
    printf("%d\\n", strlen(&arr+1));//13
    printf("%d\\n", strlen(&arr[0]+1))//14
    return 0;

//12会发生警告 

分析:

//1:数组名单独存放在sizeof()内部,计算的是整个数组的大小,结果是7

//2:  sizeof(arr + 0)计算的是数组首元素地址的大小,结果是4/8个字节

//3:  arr表示的是数组首元素的地址,*arr拿到的是数组首元素,故结果计算的是数组首元素的大小,结果是1

//4: 表示的数组第二个元素的大小,结果是1

//5:  &arr表示的是整个数组地址,计算的是整个数组地址的大小,结果是4/8个字节
//6:  &arr表示数组的地址,+ 1跳过了一个数组的大小,结果是4/8个字节

//7: &arr[0]数组首元素的地址 + 1,跳过一个char类型的大小,表示第二个元素的地址,结果是4/8个字节

//8: arr表示首元素的地址,依次往后寻找,直到找到'\\0'为止结束,结果是6

//9:  arr + 0 表示的也是数组首元素的地址依次往后寻找,直到找到'\\0'为止结束,结果为6

//10: *arr表示拿到的是数组首元素,即将'a'传进strlen函数了,会造成非法访问

//11: 也会造成非法访问

//12: &arr拿到的数组的地址,起始地址指向'a', 向后寻找'\\0',故结果为6

强调一下:这里的传址发生警告,因为&arr,放到一个指针里面去,它的类型应该是一个数组指针,为char (*)[7],但是strlen()函数的形式参数为const char * 来接收,如上图显示,会显示 “const char *”与“char (*) [7]”的间接级别不同,但是不会影响使用。

//13: &arr + 1 跳过了一个数组的大小,往后寻找'\\0',直到找到'\\0'为止结束,但这里我们并不知道'\\0'的位置,所以结果是随机值

//14: &arr[0] + 1,指向的就是第二个元素的地址,往后寻找'\\0',直到找到'\\0'为止结束,结果是5

 #inlcude<stdio.h>
int main()

    char *p = "abcdef";
    printf("%d\\n", sizeof(p));//1
    printf("%d\\n", sizeof(p+1));//2
    printf("%d\\n", sizeof(*p));//3
    printf("%d\\n", sizeof(p[0]));//4
    printf("%d\\n", sizeof(&p));//5
    printf("%d\\n", sizeof(&p+1));//6
    printf("%d\\n", sizeof(&p[0]+1));//7

    printf("%d\\n", strlen(p));//8
    printf("%d\\n", strlen(p+1));//9
    printf("%d\\n", strlen(*p));//10
    printf("%d\\n", strlen(p[0]));//11
    printf("%d\\n", strlen(&p));//12
    printf("%d\\n", strlen(&p+1));//13
    printf("%d\\n", strlen(&p[0]+1));//14
   return 0;   

分析: 

//1:这里的p是一个指针变量,指向了字符串首元素的地址,即'a'的地址,所以计算它的大小为4/8个字节

//2: p + 1指向了'b'的地址,所以计算它的大小为4/8个字节

//3: *p,即对'a'解引用操作,计算的大小就一个char 类型的大小,结果为1

//4: p[0] 等价于*(p + 0),(可以把字符串想象成一个数组,为内存连续存放的空间),即'a',结果为1

//5: &p,对指针变量p进行取地址操作,是一个一级指针的地址,为一个二级指针,但还是指针,所以大小为4/8个字节

//6: &p + 1,跳过一个char* 类型的数据,结果为4/8个字节

//7: &p[0] + 1,指向了'b'的地址,所以计算它的大小为4/8个字节
 

//8: 从'a'的地址开始,向后数,直到找到'\\0'为止结束,结果为6

//9:  p + 1 指向了'b'的地址,向后数,直到找到'\\0'为止结束,结果为5

//10: 把'a'的ascii码值当成了地址,会形成非法访问

//11: p[0]等价于*(p + 0),和*p一样,同样会造成非法访问

//12:&p是从指针变量p向后数,直到找到'\\0'为止结束,结果为随机值

//13: &p + 1跳过一个char * 类型的指针,向后数,结果也为一个随机值,但是与第十二条的随机值没有关系。(因为不确定 //12 中指针变量p中的4/8个字节空间中是否存在'\\0')

//14: &a[0]为首元素的地址,+ 1跳过一个char 类型的大小,指向了元素'b',所以计算的结果是5

3. 二维数组

#include<stdio.h>
int main()

    int a[3][4] = 0;
    printf("%d\\n",sizeof(a));//1
    printf("%d\\n",sizeof(a[0][0]));//2
    printf("%d\\n",sizeof(a[0]));//3
    printf("%d\\n",sizeof(a[0]+1));//4
    printf("%d\\n",sizeof(*(a[0]+1)));//5
    printf("%d\\n",sizeof(a+1));//6
    printf("%d\\n",sizeof(*(a+1)));//7
    printf("%d\\n",sizeof(&a[0]+1));//8
    printf("%d\\n",sizeof(*(&a[0]+1)));//9
    printf("%d\\n",sizeof(*a));//10
    printf("%d\\n",sizeof(a[3]));//11
    printf("%d\\n",sizeof(*a + 1));//12
    return 0;

分析:

//1:  二维数组名单独存放在sizeof内部,计算的是整个二维数组大小,结果是48

//2: a[0][0]即第一行第一个元素,计算的大小是4

//3: a[0]是数组第一行的数组名,这里的数组名单独存放在sizeof()内部,计算的是第一行数组的大小,结果是16

//4: a[0]不是单独存放在sizeof()内部,a[0]表示的是首元素的地址,即第一行第一个元素的地址,相当于&a[0][0],a[0] + 1就是第一行第二个元素的地址,相当于&a[0][1],计算的大小是4/8个字节

//5: *(a[0] + 1)是对第一行第二个元素的地址解引用操作,即a[0][1],计算的大小就是4

//6: a表示二维数组名,为二维数组首元素的地址,二维数组的首元素是第一行,即第一行(第一个一维数组)的地址,类型是int (*) [4],a + 1跳过第一行,指向了第二行(第二个一维数组),即第二行的地址,等价于&a[1],那么计算的结果是4/8个字节

//7:(1)对第二行的地址解引用操作。指向第二行的指针变量的大小是 int * [4],解引用访问了一个数组的大小,数组有4个元素,一个元素占4个字节,计算的总大小是16

     (2)*(a + 1)可以看作是a[1],a[1]是第二行的数组名,单独放在sizeof()内部,计算的是第二行的大小,结果是16
//8: 
&a[0] 是第一行的地址,&a[0] + 1就是第二行的地址,结果是4/8个字节

//9: &a[0] + 1是第二行的地址,*(&a[0] + 1)计算的就是第二行的大小,等价于sizeof(a[1]),结果就是16

//10: (1) a表示数组首元素的地址,即第一行的地址,*a访问的是第一行,sizeof(*a)计算的就是第一行的大小,结果是16

        (2)*a == *(a + 0)== a[0],将a[0]放在sizeof()内部,计算的也是第一行的大小,结果是16

//11:  这里的a[3]会出现越界访问吗? 结果并不会,因为sizeof这个操作符在程序编译期间就完成了操作,并不会对内部表达式进行计算,所以不会造成越界访问,编译器根据类型属性,就知道了a[3]其实和a[1]、a[2]的大小一样,都是int [4],结果就是16

//12: *a,a表示的是二维数组的数组名,数组名表示的是首元素的地址,即第一行的地址,*a得到的就是第一行,即a[0];a[0] + 1,a[0]是第一行的数组名,表示的是首元素的地址,即第一行第一个元素的地址,可以看作为&a[0][0],a[0] + 1,得到就是第一行第二个元素的地址,计算得到的结果就是4/8个字节

二、 指针笔试题

学会画图分析以下各题,更加容易让我们理解其代码的逻辑。所以画图是必不可少的!

1. 第一题

#include <stdio.h>
int main()

    int a[5] =  1, 2, 3, 4, 5 ;
    int *ptr = (int *)(&a + 1);
    printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;

分析:

 &a拿到整个数组的地址,类型是int * [5],&a + 1就跳过了5个int元素的大小,强制类型转换为int *,ptr - 1就指向了5,解引用操作打印5,*(a + 1),是数组首元素地址 + 1,解引用打印2

2. 第二题

//以下结构体的大小是20个字节
struct Test

    int Num;
    char *pcName;
    short sDate;
    char cha[2];
    short sBa[4];
* p;
//假设p 的值为0x100000。 如下表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
#include <stdio.h>
int main()

    p = (struct Test*)0x100000;
    printf("%p\\n", p + 0x1);//1
    printf("%p\\n", (unsigned long)p + 0x1);//2
    printf("%p\\n", (unsigned int*)p + 0x1);//3
 return 0;

 分析:

0x1 的意思是将十进制的1转换为了十六进制表示法。

//1: p此时是一个结构体,p + 1跳过了一个结构体的大小,跳过20个字节,即0x100020,而地址需要按十六进制打印需要打印八位,高位会补0,所以打印得到00100020

//2:  将p这个指针类型强制转换为 unsigned long 类型,即一个整型(int),那么 + 1,此时加的就是一个数字1,即0x100001

//3: 将p这个指针类型强制转换为 unsigned int*类型,+ 1跳过一个int*类型的指针,即0x100004

3. 第三题

#include<stdio.h>
int main()

    int a[4] =  1, 2, 3, 4 ;
    int *ptr1 = (int *)(&a + 1);//1
    int *ptr2 = (int *)((int)a + 1);//2
    printf( "%x,%x", ptr1[-1], *ptr2);//3
  return 0;

分析:

//1: 这里的&a拿到的就是整个数组的地址,&a + 1就跳过了一个数组,本来是int * [4]这个类型,强制类型转换成了int * ,ptr1 此时就成了一个int * 类型的指针。

//2: 这里的a是数组名,强制类型转换为整型(int),+ 1,就是加上数值1,也就是一个字节,假设a的地址是0x0012ff40,那么(int)a + 1得到的结果就是0x0012ff41,再次强制类型转换为(int *),放到整型指针ptr2之中,ptr2此时指向了内存中第二个字节的位置。

//3: (1) %x表示是用16进制进行打印输出,ptr1[-1]可以看作为*(ptr1 - 1),即指针ptr1向前跳转一个整型的大小,解引用操作,访问的就是04 00 00 00,打印出来就是4

      (2)ptr2指向了第一个元素的第二个字节处,解引用操作,访问四个字节的大小,且数组在内存中是连续存储的,如图中,灰色底纹部分就是访问的全部空间,即02 00 00 00,将其%x打印就是2000000

4. 第四题

#include <stdio.h>
int main()

    int a[3][2] =  (0, 1), (2, 3), (4, 5) ;
    int *p;
    p = a[0];
    printf( "%d", p[0]);
return 0;

老铁们,乍一看上去是不是觉得就是0了呢?哈哈哈,认为是0的老铁就踩上坑了咯~

为什么呢?下面就对题进行分析吧~

分析:

观察int a[3][2]这个数组在初始化的时候,写成了  (0, 1), (2, 3), (4, 5) ; ,而不是 0,1 ,2,3, 4,5 ;,注意里面写的是括号表达式,而不是以 的形式表示,括号表达式的运算法则是,里面的表达式从左向右计算,最后一个表达式的结果为整个逗号表达式的结果,所以数组初始化元素应该是1,3,5;   ,其余部分元素均为

a[0]即第一行的数组名,数组名是数组首元素的地址,即元素1的地址,存放到指针变量p当中去,p[0]就是*(p + 0),即对p进行解引用操作,拿到的就是1,所以结果打印1

5. 第五题

#include<stdio.h>
int main()

    int a[5][5];
    int(*p)[4];
    p = a;//1
    printf( "%p,%d\\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//2
return 0;

分析:

//1: p = a,这里的a就是数组首元素的地址,即第一行的地址,类型是int (*) [5],但是p的类型是int (*) [4],类型不同会造成什么影响吗?其实不会,就比如 int a = 10,char b =20,a = b,这样最后a的结果虽然是20,但是类型还是int类型。所以我们只是把a的地址值赋值给了b

//2: 观察上方画图,可以清晰地知道p指针在数组中的指向位置,p[4][2]即橙黄色方块的位置,&p[4][2] 指向的就是橙黄色方块,a[4][2]即黑色方块,&a[4][2]指向的就是黑色方块,前者与后者都是指针,前者减去后者得到就是中间元素个数,%d结果为 -4%p的结果打印的是地址,于是会将内存中的补码转换为十六进制数就是地址了,结果是FF FF FF FC

6. 第六题

#include<stdio.h>
int main()

    int aa[2][5] =  1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ;
    int *ptr1 = (int *)(&aa + 1);//1
    int *ptr2 = (int *)(*(aa + 1));//2
    printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1)); 
 return 0;

分析:

//1:&aa拿到整个二维数组的地址,&aa + 1跳过一个二维数组的大小, 强制类型转换成int *类型,ptr1此时也指向了这个位置。*(ptr1 - 1)打印9

//2:aa是数组名,表示数组首元素的地址,即第一行的地址,类型是int (*) [5] ,+1跳过了一个int [5]的大小,指向了第二行,类型也是int (*) [5],*解引用操作,拿到了第二行,强制类型转换为int *,此时ptr2也指向了6,*(ptr2 - 1)打印5

7. 第七题

#include <stdio.h>
int main()

    char *a[] = "work","at","alibaba";
    char**pa = a;
    pa++;
    printf("%s\\n", *pa);
return 0;

 

分析:

这里给出了一个名为a的指针数组,每个数组的类型是char*类型,实际存放的并不是"work","at","alibaba",其实是字符串首元素的地址,第一个char*指向了'w'的地址,第二个char*指向了'a'的地址,第三个char*指向了'a'的地址;数组名a是数组首元素的地址,char*的地址为char**类型,存放到pa这个二级指针中,pa++就跳过了一个char*的类型,*pa就拿到了数组第二个元素,即'a'的地址,%s打印出at

8. 第八题

#include <stdio.h>
int main()

    char *c[] = "ENTER","NEW","POINT","FIRST";
    char**cp[] = c + 3,c + 2,c + 1,c;
    char***cpp = cp;
    printf("%s\\n", **++cpp);//1
    printf("%s\\n", *-- * ++cpp + 3);//2
    printf("%s\\n", *cpp[-2] + 3);//3
    printf("%s\\n", cpp[-1][-1] + 1);//4
 return 0;

分析:

//代码的整体逻辑如上图先分析出来了。

//1: **++cpp,首先程序会执行++cpp操作,cpp会跳过一个char**的类型,此时就指向了c+2,而*一次解引用操作,我们拿到了c+2的这块空间里面的数据,即c+2,而c+2又是c数组下标为2的元素空间的地址,对其进行*解引用操作,就拿到了c数组下标为2的空间,这块空间存放了‘P’的地址,%s就会根据P的地址向后打印字符串,打印的结果就是POINT

 


 //2: *-- * ++cpp + 3,乍一看,有这么多的操作符,其实按优先级来算,还是先从++cpp开始计算,此时的cpp不再指向c+2,而是指向了c+1,然后进行*解引用操作,就拿到了c+1这块空间里面的数据,--操作,相当于c+1减去1,那么这块空间的数据就是c了,此时指向关系就再是原来的指向关系了,而是指向了c数组的第一个元素,解引用操作就拿到了数组c的第一个元素,即'E'的地址,最后+3,此时指针指向第二个'E',%s就会根据此时的地址向后打印字符串,结果打印就是ER

 


//3: *cpp[-2] + 3 ,cpp[-2]可以看作是*(cpp - 2),即 **(cpp - 2)+ 3 ,cpp - 2指向了cp数组的第一个元素的空间,*解引用操作,拿到了c+3这块空间,这块空间指向了c数组的下标为3的元素空间,解引用操作,拿到了这块空间,即'F'的地址,最后+3,指针指向了'S',%s就会根据此时的地址向后打印字符串,结果打印就是ST

 


//4: cpp[-1][-1] + 1,cpp[-1][-1] 可以看作是*(*(cpp - 1) - 1) ,即 *(*(cpp - 1) - 1),cpp - 1指向了cp数组的第二个元素的空间,*解引用操作,拿到了c+2这块空间, - 1即c+2减去1,那么这块空间的数据就是c+1了,此时指向关系就再是原来的指向关系了,而是指向了c数组的第二个元素,*解引用操作,拿到了这块空间的元素, 即'N'的地址,最后+1,指针指向了'E',%s就会根据此时的地址向后打印字符串,结果打印就是EW

好了,题目就到这里了,如果能对以上指针题目理解通透,那么C语言指针就没多大问题啦,而以上题目基本上需要我们去画图理解!可以看出理解代码的逻辑时画图有多么的重要!~


✨✨ 创作不易,希望能的到小伙伴的三连,感谢各位小伙伴的支持哦~~

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

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

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

C语言指针文章目录C语言指针1.字符串指针2.指针数组3.数组指针4.数组参数,指针参数5.函数指针-指向函数的指针6.函数指针数组7.库函数qsort的用法:qsort(void*p,intnum1,intnum2,int(*cmp)(counstvoid*e1,counstvoid*e2))8.指针和数组练习题1.字符串指... 查看详情

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

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

经典指针和数组面试题详解(代码片段)

指针和数组笔试题1. intmain() inta[5]=1,2,3,4,5; int*ptr=(int*)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); system("pause"); return0;(a+1)就是a[1]的地址&#x 查看详情

70道指针数组笔试题(代码片段)

本文指针数组笔试题可以用来检测你对指针的掌握程度ヽ( ̄▽ ̄)ノ大家自己看看自己对指针掌握怎么样吧!温馨提示:建议大家先看目录中的题先自行思考一下,再去点击对照(默认32位条件)文... 查看详情

c语言的罗盘——指针!深入理解c语言指针及其应用(代码片段)

...;字符串库函数和指针等内容,在这篇文章我们将继续深入了解有关字符串库函数和指针的探索。📒博客主页:https://blog.csdn.net/m0 查看详情

深入理解指针与数组(代码片段)

...时隔许久又一良心巨著,主要是介绍了指针和数组的一些深入的理解,特意整理出来一篇博客供我们一起学习,如果文章中有理解不当的地方,还希望朋友们在评论区指出,我们相互学习,共同进步!文章目录一:指针1.1什么是指针1.2... 查看详情

c语言进阶笔记深入了解进阶指针(代码片段)

目录前言指针进阶字符指针指向常量字符串的指针指针数组指针数组打印数组内容数组指针对数组指针的理解&数组名和数组名数组指针的使用数组参数、指针参数一维数组传参二维数组传参一级指针传参二级指针传参函数指... 查看详情

c语言进阶笔记深入了解进阶指针(代码片段)

目录前言指针进阶字符指针指向常量字符串的指针指针数组指针数组打印数组内容数组指针对数组指针的理解&数组名和数组名数组指针的使用数组参数、指针参数一维数组传参二维数组传参一级指针传参二级指针传参函数指... 查看详情

详解c语言指针(代码片段)

文章目录1.字符指针2.指针数组3.数组指针3.1数组指针的定义3.2&数组名和数组名的区别3.3数组指针的使用4.数组参数,指针参数4.1一维数组传参4.2二维数组传参4.3一级指针传参4.4二级指针传参5.函数指针6.函数指针数组7.指向... 查看详情

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

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

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

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

动态内存管理(动态内存函数的介绍,c/c++经典笔试题,柔性数组)(代码片段)

...️calloc✏️realloc🎓常见的动态内存错误🎓几个经典的笔试题🎓C/C++程序的内存开辟&#x 查看详情

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

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

c语言中的指针,数组和结构体结合的一个经典案例(代码片段)

...题,就卡住了。这里,有一个问题,可以考察你对这三者理解如何。二一个例子: #include<stdio.h>typedefunsignedcharuint8_t;typedefstructuint8_tssid[32];/**<SSIDofESP8266sof 查看详情

c语言进阶笔记深入了解进阶指针(代码片段)

目录前言指针进阶字符指针指向常量字符串的指针指针数组指针数组打印数组内容数组指针对数组指针的理解&数组名和数组名数组指针的使用数组参数、指针参数一维数组传参二维数组传参一级指针传参二级指针传参函数指... 查看详情

动态内存管理详解(动态内存函数介绍+常见动态内存错误+经典笔试题)(代码片段)

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

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

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