c语言学习第二十一课-指针和数组笔试题解析

本文涉及的产品
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: c语言学习第二十一课-指针和数组笔试题解析

要想熟练的面对数组与指针方面的笔试题。首先我们先大致了解一下,关于数组与指针。

一,数组

数组的构成是 数据类型+数组名[常量表达式],数组无法直接引用其全部,只能逐一的引用数组元素,数组的表达形式是数组名[下标]。

对于数组用来传参,数组名一般代表数组首元素地址。

二,指针

首先指针就是地址,定义形式为  指针类型+变量名称,这个变量里的数值被认定为内存里的地址。对于指针,我们要详细的了解其指针的类型,指针指向的类型。

int *a;//指针的类型是int *型,指针指向的类型是int型
int **a;//指针的类型是int **型,指针指向的类型是int *型
int(*a)[3];//指针的类型是int (*)[]型,指针指向的类型是 int()[]型

数组与指针

指针->地址,指针变量->大小4/8字节

数组,大部分情况数组名就是数组首元素地址  但有两个例外

sizeof(数组名)  

&数组名-数组名表示整个数组-取出的是数组地址

这两个数组名代表的是整个数组的地址

一般的,指针与数组可以相对的表示 *a->&a[o]->a[0]

这里的考察主要通过 操作符sizeof与函数strlen两个对数组与指针的考察,但在此前,先了解一下

操作符sizeof()

sizeof()作为一个单目运算符,是用来计算对应操作数的所占空间大小,它里面的参数可以是,数组,指针,函数,类型等。不管是是什么,都是计算对应数所占空间大小,单位是字节。

对于sizeof(),sizeof表达式不会真的去访问它,只看类型.

  /*
    * int a=5;
    * short s=11;
    * printf("%d\n",sizeof(s=a+2));//2  short类型,sizeof只看类型,不计算
    * printf("%d\n",s);// 实际为7    但不计算,还是11
    * return 0
    * 
    * 对于表达式a+3有两种类型:
    * 值属性
    * 类型属性      //sizeof()只关注类型属性,不关注值属性
    */

函数strlen()

strlen()函数是用来求字符串长度

strlen只针对字符串,求的是字符串的长度。本质上是“\0”前的字符长度,其参数是指针才可以,否则会造成非法访问,若无“\0”,则长度为随机值

例题展示

现在我们来深入sizeof与strlen,举例一个整型数组,此时用sizeof 计算

     int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));//16
  //szieof)(a)就是数组名单独放在sizeof内部,计算数组总大小,单位是字节
  printf("%d\n", sizeof(a + 0));//4/8个字节
  //a+0其实是数组首元素地址
  printf("%d\n", sizeof(*a));//4
  //数组首元素
  //*a->&a[o]->a[0]
  printf("%d\n", sizeof(a + 1));//4/8个字节
  //a是数组首元素,a+1是第二个元素的地址
  printf("%d\n", sizeof(a[1]));//4
  printf("%d\n", sizeof(&a));//4或者8
  //&a-取出的是整个数组的地址。是一个地址
  //int (*pa)[4]=&a;int (*)[4]
  printf("%d\n", sizeof(*&a));//16
  //sizeof(a);
  //int (*)a;
  printf("%d\n", sizeof(&a + 1));//4/8
  //&a+1跳过一个数组,在该数组地址末尾
  printf("%d\n", sizeof(&a[0]));//4/8
  printf("%d\n", sizeof(&a[0] + 1));//4/8
  //第二个元素的地址

在上面中,若a单独放进sizeof中,就是正常作用,此时a代表整个数组,计算总空间大小为4*4个字节,若没有单独放,如a+0;那么a代表首元素地址,加零还是首元素地址,地址的大小为4或8个字节。其次sizeof(&a)这里取出的地址是整个数组的地址,int (*pa)[4]=&a,数组与指针的相互表示。若&a+1则表示跳过这个数组这一块空间,

a7c1ed8bf5c140f6845d5d3377e50d48.png

之后我们再以arr的字符型数组为例,用sizeof()来计算一次

    char arr[] = { 'a','b','c','d','e','f'};
    printf("%d\n", sizeof(arr));//6
  printf("%d\n", sizeof(arr + 0));//4/8
  //数组首元素的地址
  printf("%d\n", sizeof(*arr));//1
  //表示首元素地址,单独放进来的*,是首元素。
  printf("%d\n", sizeof(arr[1]));//1
  printf("%d\n", sizeof(&arr));//4/8
  //取出的是全部地址,但也是一个地址
  printf("%d\n", sizeof(&arr + 1));//4/8
  //末尾地址
  printf("%d\n", sizeof(&arr[0] + 1));//4/8
  //第二个元素地址

上面的数组类型不一样,计算的空间大小不一样,但本质都是看对于 arr   arr +0  *arr  *arr+ 1    &arr   &arr+1   a[0]   等的本质理解它是代表什么。

我们在举例关于strlen的计算,

char arr[] = { 'a','b','c','d','e','f' };
  printf("%d\n", strlen(arr));//随机值
  //arr数组名,首元素地址,但不知道什么时候遇到‘\0’
  printf("%d\n", strlen(arr + 0));//随机值
  //+0还是首元素地址
  printf("%d\n", strlen(*arr));//非法访问
  //放的不是地址,*arr=a[0]是‘a'
  printf("%d\n", strlen(arr[1]));//无非访问
  //与上同理
  printf("%d\n", strlen(&arr));//随机值
  //无法确定“\0”的位置
  printf("%d\n", strlen(&arr + 1));//随机值-6
  //末尾地址,找不到’\0‘
  printf("%d\n", strlen(&arr[0] + 1));//随机值-1
  //第二个地址往后,找不到’\0‘

以上字符数组例子都是在数组中无法找到“\0”的,所以在计算时会出现随机值。

若改变数组再利用sizeof 与strlen 各计算一遍

char arr[] = "abcdef";//[a,b.c.d.e.f,\0]
  printf("%d\n", sizeof(arr));//7
  //计算数组大小,7个字节
  printf("%d\n", sizeof(arr + 0));//4/8
  printf("%d\n", sizeof(*arr));// 1
  //数组首元素。*arr= (*arr+0)= arr[0] 
  printf("%d\n", sizeof(arr[1]));//1
  printf("%d\n", sizeof(&arr));//4/8
  printf("%d\n", sizeof(&arr + 1));//4/8
  printf("%d\n", sizeof(&arr[0] + 1));//4/8
  printf("%d\n", strlen(arr));//6
  printf("%d\n", strlen(arr+0));//6
    //从首元素开始计算
  printf("%d\n", strlen(*arr));//无法访问
  printf("%d\n", strlen(&arr));//6
  //取出的类型不一样,但不影响
  printf("%d\n", strlen(&arr+1));//随机值
    //在末尾地址
  printf("%d\n", strlen(arr[0]+1));//5

对于arr在取地址操作时,他取出的是整个数组的地址。

此外对于一个变量指针存放数组再计算.,比较sizeof与strlen的区别。

int main()
{
  char* p = "abcdef";
  printf("%d\0", sizeof(p));//4/8
  //指针的大小
  printf("%d\0", sizeof(p + 1));//4/8
  //指向第二个元素的地址
  printf("%d\0", sizeof(*p));//1
  //表示首字符
  printf("%d\0", sizeof(p[0]));//==*(p+0)  为1
    //可以理解为一个数组
  printf("%d\0", sizeof(&p));//4/8
  //取出的是地址,开辟p时的地址,与abcdef无关
  printf("%d\0", sizeof(&p + 1));//4/8
  //跳过一个p
  //char *p;char* *p=&p;
  printf("%d\0", sizeof(&p[0]+1));//4/8
  //b的地址
  printf("%d\n", strlen(p));//6
  printf("%d\n", strlen(p+1));//5
  //跳过一个地址
  printf("%d\n", strlen(*p));//非法访问
  printf("%d\n", strlen(p[0]));//非法访问
  printf("%d\n", strlen(&p));//随机值
  //在地址里找'\0’
  //不知哪里有”\0“
  printf("%d\n", strlen(&p + 1));//随机值
  printf("%d\n", strlen(p[0] + 1));//5
}

这里用指针表示数组,效果一样,我们可以直接理解为数组放进去。除了数组名单独放,它都是一个表示首元素地址的效果(&p,代表取出整个地址),才是也是无法找到“\0”。

这里我们再用二维数组举例,再看sizeof与strlen在这里的情况。

int main()//二维数组数组名没单独放。则是第一行地址
{
  int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));//a的数组名单独放在sizeof里 代表所有大小  48
  printf("%d\n", sizeof(a[0][0]));//第一行第一个元素   4
  printf("%d\n", sizeof(a[0]));//16 第一行的数组名,数组名单独放在sizeof内部。
  printf("%d\n", sizeof(a[0]+1));//4 不是单独放在sizeof里    a[0]代表首元素地址  是第一行第二个元素地址
  printf("%d\n", sizeof(*(a[0]+1)));// a[0][1]大小 4个字节
  printf("%d\n", sizeof(a+1));//a代表第一行的地址类型  加一为 第二行的地址 4/8
  printf("%d\n", sizeof( * (a + 1)));//16
  //第二行的大小  
  printf("%d\n", sizeof(&a[0]+1));//取出第一行的地址 加一  第二行的地址 4/8
  printf("%d\n", sizeof(*(&a[0] + 1)));  //第二行的元素大小  16
  printf("%d\n", sizeof(*a));//表示第一行的大小  16
  printf("%d\n", sizeof(a[3]));//第四行元素  16  四个0  
}

对于二维数组,sizeof(a)

我们知道二维数组是连续储存的,那么它的结构应该是这样。


275f1c040c194dbcab6bf80af2171f16.png

,这里的a[0]单独放表示第一行整个的所有元素,a不单独放代表的是第一行的整个地址。

且在最后一个例子当中我们发现sizeof并没有说越界访问,这是因为sizeof只看数据类型,不看值类型,在sizeof中参数表达式不会被计算。

对于sizeof(*arr+1) ,a若单独放*a=arr[0],是代表第一行的元素。 不是单独放,则为首元素地址所以这里是第二个元素。

看完以上这个,举个笔试题。

int main()
{
  int a[5] = { 1,2,3,4,5 };
  int* ptr = (int*)(&a + 1);
  printf("%d %d", *(a + 1), *(ptr - 1));//2 5
  //a是首元素地址在&a+1中。a是全部地址在ptr中
  return 0;
}

这里我们可以看到&a是去除的是整个该数组的地址,且a表示首元素地址。

以上便是今天学习的内容了。

大家一起加油o

相关文章
|
6天前
|
存储 C++
有关【指针运算】的经典笔试题
有关【指针运算】的经典笔试题
12 4
|
5天前
|
存储 编译器 C语言
c语言学习历程【1】
c语言学习历程【1】
8 1
|
2天前
|
C语言
C语言实现猜数字游戏:代码详解与函数解析
C语言实现猜数字游戏:代码详解与函数解析
5 0
|
3天前
|
自然语言处理 C语言 C++
程序与技术分享:C++写一个简单的解析器(分析C语言)
程序与技术分享:C++写一个简单的解析器(分析C语言)
|
4天前
|
C语言
|
6天前
|
C语言
|
6天前
|
C语言
|
1天前
|
Java C语言 C++
定义C语言的int main()函数
定义C语言的int main()函数
|
4天前
|
C语言
C语言prinf函数
C语言prinf函数
11 4

推荐镜像

更多