C语言: 数组指针/指针数组等相关的选择题目

简介: C语言: 数组指针/指针数组等相关的选择题目

写在前面

本篇总结的是和指针相关的有难度的选择题,并对这些题进行解析和分析

形参和实参

下面程序的运行结果是什么?

#include <stdio.h>
void func(char* p)
{
  p = p + 1;
}
int main()
{
  char s[] = { '1','2','3','4' };
  func(s);
  printf("%c", *s);
  return 0;
}

首先传参是数组名,这里的数组名代表的是首元素的地址,但传过去的并不是数组名的地址,func函数内部对p的改变不改变外部数组s,因此输出的应该为1

二维数组传参

已知数组D的定义是int D[4][8],现在要把这个数组作为实参传递给一个函数处理,下列可以作为形参变量的是

A. int D[4][] B. int *s[8] C. int(*s)[8] D. int D[][8]

这里的数组D是一个二维数组,那么就首先要清楚二维数组传参传的是什么,二维数组传参传递的是二维数组中首元素的地址,也就是第一个一维数组的地址,也就是数组指针

数组指针是一个指向数组的指针

int *s[8] -> 这是指针数组,数组名是s,里面存着8个指针

int (*s)[8] -> 这是数组指针,指针名是s,指针指向一个大小为8的数组

因此这里ABCD中要选一个数组指针,因此选的是C

字符数组

下面程序的运行结果是什么?

#include <stdio.h>
void fun(char** p)
{
  int i;
  for (i = 0; i < 4; i++)
  {
    printf("%s", p[i]);
  }
} 
int main()
{
  char* s[6] = { "ABCD", "EFGH", "IJKL", "MNOP", "QRST", "UVWX" };
  fun(s);
  printf("\n");
  return 0;
}

char类型的数组内只能存储单个字符,这里改成了char*类型的数组,意思就是存储的是这些字符串的地址,因为一个字符串会被编译器看成const char*类型,因此存储到数组中相应的数组的类型就是char*类型的数组

而fun函数传参,传的是数组,数组名代表的是首元素的地址,因此接收函数的形参类型就是char**

而函数中的p[i]又可以看成是*(p+i),因此输出的就是ABCDEFGHIJKLMNOP

二维数组

数组a的定义为int a[3][4],下面哪个不能表示a[1][1]

A. *(&a[0][0]+5) B. *(*(a+1)+1) C. *(&a[1]+1) D. *(a[1]+1)

先看A选项,&a[0][0]表示二维数组中元素的地址,该元素的地址+5表示向后加5个元素的地址,再对该地址进行解引用,得出的就是a[1][1]

再看B选项,*(a+1)表示的就是a[1],而*(a[1]+1)表示的就是a[1][1]

再看C选项,应该改为*(&a[1][0]+1),因为a[1]就表示a[1][0]的地址

D选项,由B选项可知这是正确的

函数指针数组

void (*s[5])(int) 是什么意思?

这里涉及到的是函数指针数组的概念,s首先和[]结合,证明这里的s是一个数组,数组中存储的内容类型是void (*)(int),那这又是什么?这就是函数指针,该指针指向的函数的参数是int,返回类型是void

参数匹配

  1. 下面参数调用匹配的是
void f(int** p);
int a[4] = { 1,2,3,4 };
int b[3][4] = { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
int* q[3] = { b[0],b[1],b[2] };
A.f(a) B.f(b)  C.f(q)  D.f(&a) 

这里需要f函数的参数是int**,意味着传参的参数要和这个匹配

A:如果传参的参数是a,这里的a代表的是首元素的地址,对应的参数应该是int*

B:如果传参的参数是b,由于b是二维数组,传参传的是二维数组中第一个数组的地址,传的是数组指针,对应的参数是int (*)[]

C:这个是符合的,传参首元素的地址,对应的是int**

D:&a表示的取出的是整个数组的地址,和A选项从数值上来看是一样的,区别是+1的问题

  1. 有定义语句:char s[3][10],(*k)[3],*p,下面赋值错误的是

p=s; p=k; p=s[0]; k=s;

因此这里就要看s,k,s[0],p分别代表什么类型了

首先看s:s是二维数组,因此这里s的类型是数组指针->char (*)[]

再看k:k就是数组指针,类型和s相同char (*)[]

再看s[0]:s[0]是二维数组中第一行数组,因此s[0]是一个一维数组,对应类型就是char*

最后是p:p类型是char*,这个很明显

因此赋值等号两边类型得相同,因此第一个第三个第四个都不同

  1. 下面对fun函数调用正确的是:
char fun(char*);
int main()
{
  char* s = "one";
  char a[5] = { 0 };
  char (*f1)(char*) = fun;
  char ch;
  return 0;
}

A: *f1(&a);

B: f1(*s);

C: f1(&ch);

D: ch = *f1(s);要改成(*f1)(s)才正确

首先看函数,定义了一个字符串s,第二个定义了一个字符数组,内的元素都是0,重点看f1:

f1是函数指针,f1指向的函数参数是char*,返回值是char,也就是说f1是函数fun的指针

那么分析选项:

首先要分清楚,(*f1)(&a)f1(&a)*f1(&a)

在函数指针调用中(*f1)(&a)f1(&a)效果是一样的,但是*f1(&a)会被认为是对返回值的解引用

A: *f1(&a);:括号的优先级大于解引用,&a表示的是取出数组a的地址,类型是char*符合函数指针调用参数,因此f1(&a)会返回char类型的数据,但对它解引用这是错误的

B: f1(*s);:*s参数不匹配

C: f1(&ch);:没问题

D: ch = *f1(s);要改成(*f1)(s)才正确:区分清上面的含义这个不难理解

多级指针

下面程序运行结果是?

#include<stdio.h>
int main()
{
  static char* s[] = { "black", "white", "pink", "violet" };
  char** ptr[] = { s + 3, s + 2, s + 1, s }, *** p;
  p = ptr;
  ++p;
  printf("%s", **p + 1);
  return 0;
}

首先定义了s数组,里面存的是字符串首元素的地址

下面的ptr是二级指针,存储的是s数组的,拿其中一个进行分析,ptr数组中存储的s+1,实际上对应的是s数组中下标为1的元素对应的地址,而又由于s数组中下标为1的元素是一个指针,因此这里ptr存储的是一个二级指针

后面又定义了p,ptr表示的是s+3的地址,s+3本身是二级指针,因此ptr就是三级指针

++p表示此时p由原来指向的s+3变成了s+2

在后面输出的部分,p现在指向的是s+2,因此*p就是s+2,再对它解引用*pp也就是*(s+2)也就是s[2],而s[2]对应的是pink,因此这里指向的就是p,再+1指向的就是i,因此打印结果就是ink

相关文章
|
4天前
|
编译器 C语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下
|
4天前
|
存储 C语言
【C语言初阶】指针篇—上
【C语言初阶】指针篇—上
|
14天前
|
搜索推荐 程序员 C语言
指针赋值与引用传递:C语言的基础知识与实践技巧
指针赋值与引用传递:C语言的基础知识与实践技巧
|
2天前
|
安全 C语言
C语言8 数组与字符串
C语言8 数组与字符串
5 0
|
7天前
|
存储 编译器 定位技术
结构体数组在C语言中的应用与优化策略
结构体数组在C语言中的应用与优化策略
|
13天前
|
存储 编译器 数据库
结构体数组在C语言中的应用与优化技巧
结构体数组在C语言中的应用与优化技巧
|
13天前
|
搜索推荐 程序员 C语言
指针赋值与引用传递:C语言的基础知识与实践技巧
指针赋值与引用传递:C语言的基础知识与实践技巧
|
17天前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
19 0
|
18天前
|
C语言
C语言中的函数指针、指针函数与函数回调
C语言中的函数指针、指针函数与函数回调
11 0