Login
欢迎访问考试集-www.kaoshiji.cn 考试集,让考试更简单!懂考试,更懂你!
我要投稿 请登录 免费注册 安全退出

第8章试卷《C程序设计》谭浩强主编教材-清华大学出版社-2017年8月第五版-ISBN:978-7-302-48144-7-章节练习题库

更新时间: 2025-03-30 加入收藏 立即下载

试卷页数】:共104页/预览前10页

试卷大小6.37M

下载方式】:百度网盘

 提 取 码】:rguf

下载地址】:https://www.kaoshiji.cn/jsjkxjs/651.html


教材名称:C程序设计》

主编谭浩强

出版社:清华大学出版社

版次:20178月第五版

书刊号:ISBN978-7-302-48144-7

                                                    

 

考试集教材配套题库介绍 

一、精准匹配教材,一站式学习解决方案 

二、题库核心优势 

一、 单项选择题(60题) 

二、多项选择题(40题) 

三、判断题(40题) 

四、填空题(40题) 

五、名词解释题(40题) 

六、 简答题(40题) 


考试集教材配套题库介绍

一、精准匹配教材,一站式学习解决方案

本网站专注于为高等教育教材,提供全章节配套题库服务,完全覆盖教材知识点。题库设计严格遵循教材章节结构,助力学习者系统掌握知识体系。

二、题库核心优势 

1.题量丰富,解析详尽 

每章独立题库,总计超千道高质量试题。每题均附标准答案+逐题解析,深入剖析考点,帮助学生举一反三。  

2.灵活下载,多端适配  

支持题库下载,满足打印、笔记等个性化学习需求。配套手机在线刷题小程序,随时随地碎片化学习,自动记录进度与错题。  

3. 智能功能,高效提分  

小程序智能归纳易错题型,针对性强化薄弱环节。限时自测,还原真实考试环境,提升应试能力。  

考试集官网[www.kaoshiji.cn]下载试题

关注微信公众号:百业先生,为您提供一站式服务。

第8章试卷《C程序设计》谭浩强主编教材-清华大学出版社-2017年8月第五版-ISBN:978-7-302-48144-7-章节练习题库(图1)

 

扫一扫,码上刷题

考试集,让学习更简单!

                                             

8章试卷-章节练习

8章善于利用指针217

8.1指针是什么217

8.2指针变量219

8.2.1使用指针变量的例子219

8.2.2怎样定义指针变量220

8.2.3怎样引用指针变量222

8.2.4指针变量作为函数参数224

8.3通过指针引用数组229

8.3.1数组元素的指针229

8.3.2在引用数组元素时指针的运算229

8.3.3通过指针引用数组元素231

8.3.4用数组名作函数参数236

8.3.5通过指针引用多维数组243

8.4通过指针引用字符串254

8.4.1字符串的引用方式 254

8.4.2字符指针作函数参数258

8.4.3使用字符指针变量和字符数组的比较262

8.5指向函数的指针265

8.5.1什么是函数的指针265

8.5.2用函数指针变量调用函数265

8.5.3怎样定义和使用指向函数的指针变量267

8.5.4用指向函数的指针作函数参数269

8.6返回指针值的函数273

8.7指针数组和多重指针276

8.7.1什么是指针数组 276

8.7.2指向指针数据的指针变量279

8.7.3指针数组作main函数的形参281

8.8动态内存分配与指向它的指针变量284

8.8.1什么是内存的动态分配284

8.8.2怎样建立内存的动态分配284

8.8.3void指针类型 286

8.9有关指针的小结288

                                            

一、 单项选择题(60题)

1.下列关于指针变量的描述中,错误的是

A. 指针变量存储的是内存地址

B. 指针变量可以进行加减运算

C. 指针变量可以直接存储字符串

D. 指针变量可以指向数组元素

正确答案:C

解析:指针变量存储的是内存地址,可以通过地址进行加减运算来访问不同的内存位置,也可以指向数组元素。但是指针变量本身不能直接存储字符串,它只能存储字符串(字符数组)的首地址。

2.在C语言中,若要通过指针引用数组元素,下列哪个表达式是正确的

A. *(p+i)

B. p[i]

C. &p[i]

D. p.i

正确答案:A

解析:在C语言中,p是一个指向数组首元素的指针,*(p+i)和p[i]都是访问数组第i+1个元素的正确方式。&p[i]是取数组第i+1个元素的地址,而p.i在C语言中不是有效的语法。

3.关于字符指针和字符数组,以下说法不正确的是

A. 字符数组名可以作为字符串的指针

B. 字符指针可以指向一个字符串常量

C. 字符数组可以整体赋值,字符指针不可以

D. 字符指针和字符数组都可以直接修改其内容

正确答案:D

解析:字符数组名在大多数表达式中会被解释为指向数组首元素的指针,因此A正确。字符指针可以指向字符串常量或字符数组的首地址,因此B正确。字符数组可以在初始化时整体赋值,而字符指针通常需要通过指向已有的字符串或动态分配内存并赋值,因此C正确。但是,如果字符指针指向的是字符串常量,那么尝试修改其内容会导致未定义行为,因为字符串常量通常存储在只读内存区域,所以D不正确。

4.下列关于函数指针的描述中,正确的是

A. 函数指针就是函数的地址

B. 函数指针可以指向任何类型的函数

C. 定义函数指针时不需要指定函数的返回类型

D. 通过函数指针调用函数时,不需要使用解引用操作符

正确答案:D

解析:函数指针是存储函数地址的指针变量,但说它“就是”函数的地址不够准确,应该是它“存储”了函数的地址,因此A不完全正确。函数指针必须指向与其签名(包括返回类型和参数类型)相匹配的函数,因此B错误。定义函数指针时需要指定函数的返回类型以及参数类型,因此C错误。通过函数指针调用函数时,直接使用函数指针名加上括号和参数即可,不需要使用解引用操作符(*),因此D正确。

5.在C语言中,动态内存分配通常使用哪个函数? 

A. malloc

B. calloc

C. realloc

D. 以上都是

正确答案:D

解析:在C语言中,malloc用于分配指定字节数的内存,calloc用于分配内存并初始化为零,realloc用于重新分配已经分配的内存块的大小。这三个函数都是用于动态内存分配的,因此D选项“以上都是”是正确的。

6.在C语言中,若有一个整型数组int arr[10];,则下列哪个表达式不能表示数组arr中元素的地址? 

A. &arr[0]

B. arr

C. arr+1

D. *(arr+1)

正确答案:D

解析&arr[0]表示数组第一个元素的地址,arr在大多数表达式中等价于&arr[0],也表示数组第一个元素的地址。arr+1表示数组第二个元素的地址(因为指针加1意味着地址向前移动一个整型的大小)。而*(arr+1)是解引用操作,它表示的是数组第二个元素的值,而不是地址。

7.关于字符指针和字符串,以下说法正确的是

A. 字符指针就是字符串

B. 字符串常量可以被字符指针修改

C. 字符指针必须指向字符数组的首元素

D. 字符指针可以指向字符串常量的首字符

正确答案:D

解析:字符指针是存储字符地址的指针变量,它本身不是字符串,而是指向字符串(或字符)的指针,因此A错误。字符串常量通常存储在只读内存区域,不能被字符指针修改,尝试修改会导致未定义行为,因此B错误。字符指针可以指向任何字符的地址,包括字符数组中的任意元素,不仅仅是首元素,因此C错误。字符指针可以指向字符串常量的首字符,这是常见的用法,因此D正确。

8.在C语言中,若有一个函数int func(int a, int b);,则下列哪个是正确定义指向该函数的指针的方式? 

A. int *func_ptr(int, int);

B. int (*func_ptr)(int, int);

C. int *func_ptr;

D. int func_ptr(int, int);

正确答案:B

解析:定义指向函数的指针时,需要指定函数的返回类型、指针名以及函数的参数类型。选项B正确地定义了指向返回类型为int,参数类型为两个int的函数的指针。选项A错误地尝试定义了一个返回类型为int*,参数类型为两个int的函数,而不是指针。选项C定义了一个指向int的指针,而不是函数指针。选项D定义了一个返回类型为int,参数类型为两个int的函数,也不是指针。

9.在C语言中,若有一个指针数组char *str_array[5];,则下列哪个描述是正确的? 

A. str_array是一个指向字符的指针

B. str_array是一个包含5个字符的数组

C. str_array是一个包含5个字符指针的数组

D. str_array是一个指向5个字符指针的指针

正确答案:C

解析char *str_array[5];定义了一个包含5个元素的数组,每个元素都是指向char的指针,即字符指针。因此,str_array是一个包含5个字符指针的数组。选项A错误地描述了它是一个指向字符的指针(实际上它是一个数组)。选项B错误地描述了它是一个包含5个字符的数组(实际上它包含的是指针)。选项D错误地描述了它是一个指向5个字符指针的指针(实际上它是一个数组,不是指针的指针)。

10.在C语言中,使用malloc函数动态分配内存后,如果不再需要这块内存,应该使用哪个函数来释放它? 

A. free

B. delete

C. release

D. dispose

正确答案:A

解析:在C语言中,使用malloc(或calloc、realloc)函数动态分配的内存,当不再需要时,应该使用free函数来释放它,以避免内存泄漏。delete是C++中用于释放动态分配内存的运算符,不是C语言中的函数。release和dispose也不是C语言中用于释放内存的标准函数。

11.在C语言中,若有一个指向整型的指针int *p;,并且p已经指向了某个整型变量,那么下列哪个操作可以正确地获取p所指向的变量的值? 

A. p

B. *p

C. &p

D. p*

正确答案:B

解析:在C语言中,p是一个指向整型的指针,它存储的是某个整型变量的地址。要获取p所指向的变量的值,需要使用解引用操作符*,即*p。选项A中的p表示的是指针本身,而不是它所指向的值。选项C中的&p表示的是指针p的地址,而不是它所指向的变量的值。选项D中的p*是语法错误,正确的解引用应该是*p。

12.关于void指针类型,以下说法不正确的是

A. void指针可以指向任何类型的数据

B. void指针不能直接解引用

C. void指针可以与其他类型的指针直接进行算术运算

D. void指针通常用于函数参数和返回值,以实现通用性

正确答案:C

解析void指针是一种特殊的指针类型,它可以指向任何类型的数据,但是不能直接解引用,因为编译器不知道它所指向的数据的类型和大小。void指针通常用于函数参数和返回值,以实现函数的通用性。然而,void指针不能与其他类型的指针直接进行算术运算,因为算术运算需要知道指针所指向的数据类型的大小。在进行算术运算之前,通常需要将void指针转换为具体类型的指针。

13.在C语言中,若有一个函数void func(int *arr, int size);,该函数接受一个整型数组和一个表示数组大小的整数作为参数。在函数内部,若要通过指针访问数组的第二个元素,下列哪个表达式是正确的? 

A. arr[1]

B. *(arr+1)

C. arr+1

D. &arr[1]

正确答案:A

解析:(本题为单选,但A和B都是正确的,选择最直接的答案A)在C语言中,数组名在大多数表达式中会被解释为指向数组首元素的指针。因此,在函数func内部,arr是一个指向整型数组的指针。要通过指针访问数组的第二个元素,可以使用数组下标访问方式arr[1],或者使用指针加偏移量的方式*(arr+1)。选项C中的arr+1表示的是指向数组第二个元素的指针,而不是元素本身。选项D中的&arr[1]表示的是数组第二个元素的地址,也不是元素本身。

14.关于指针数组,以下说法不正确的是

A. 指针数组是一个数组,其元素都是指针

B. 指针数组可以用于存储多个字符串的地址

C. 指针数组的每个元素都可以指向不同类型的数据

D. 指针数组可以作为函数的参数,以实现函数的通用性

正确答案:C

解析:指针数组是一个数组,其元素都是指针,这是正确的。指针数组可以用于存储多个字符串的地址,因为字符串的地址就是指向字符串首字符的指针。指针数组也可以作为函数的参数,以实现函数的通用性,比如可以传递一个指向不同数据类型的指针数组给函数,函数根据指针的类型来处理不同的数据。然而,指针数组的每个元素并不一定都可以指向不同类型的数据,这取决于指针数组的定义。通常,指针数组的元素会指向相同类型的数据,以便于统一处理。如果允许每个元素指向不同类型的数据,那么在使用时需要特别小心,以避免类型错误。

15.在C语言中,若要使用malloc函数动态分配一块足够存储10个整型的内存,并将分配的内存地址赋值给指针p,下列哪个代码片段是正确的? 

A. int *p; p = malloc(10);

B. int *p; p = (int *)malloc(10 * sizeof(int));

C. int p; p = malloc(10 * sizeof(int));

D. int *p = malloc(10 * sizeof(int));

正确答案:B

解析:(本题为单选,但B和D都是正确的,选择最完整的答案B)在C语言中,要使用malloc函数动态分配内存,需要指定要分配的字节数,并且需要将返回的地址转换为适当的指针类型。选项A中的malloc(10);分配了10个字节的内存,而不是10个整型所需的内存。选项B中的(int *)malloc(10 * sizeof(int));正确地分配了足够存储10个整型的内存,并将返回的地址转换为int*类型,然后赋值给指针p。选项C中的int p;声明了一个整型变量,而不是指针,因此不能存储malloc返回的地址。选项D中的int *p = malloc(10 * sizeof(int));也是正确的,它声明了一个指向整型的指针,并直接将其初始化为malloc返回的地址。

16.在C语言中,若有一个整型数组int arr[10];,并且有一个指向整型的指针int *p;,要将指针p指向数组的最后一个元素,下列哪个操作是正确的? 

A. p = arr[9];

B. p = &arr[9];

C. p = arr; p += 9;

D. p = arr[10];

正确答案:B

解析:(本题为单选,但B和C都是正确的,选择最直接的答案B)在C语言中,数组名arr代表数组的首地址,即指向数组第一个元素的指针。要访问数组的最后一个元素,可以使用下标访问方式arr[9],但这将直接获取元素的值,而不是地址。要将指针p指向数组的最后一个元素,需要获取该元素的地址,即使用&arr[9]。选项C中的p = arr; p += 9;也是正确的,它首先将指针p指向数组的首地址,然后通过指针运算将其移动到数组的最后一个元素的位置。选项A中的p = arr[9];是错误的,因为它将数组最后一个元素的值赋给了指针p,而不是地址。选项D中的p = arr[10];也是错误的,因为数组下标是从0开始的,arr[10]是越界的访问。

17.关于指向函数的指针,以下说法不正确的是

A. 指向函数的指针可以存储函数的地址

B. 指向函数的指针可以作为函数的参数

C. 指向函数的指针可以直接调用它所指向的函数

D. 指向函数的指针可以改变它所指向的函数的代码

正确答案:D

解析:指向函数的指针是C语言中的一种特殊指针,它可以存储函数的地址,从而可以在程序的运行过程中动态地调用函数。指向函数的指针可以作为函数的参数,这样可以使函数更加灵活和通用。指向函数的指针也可以直接调用它所指向的函数,这是通过解引用指针来实现的。然而,指向函数的指针并不能改变它所指向的函数的代码,因为函数的代码在程序编译时就已经确定了,而且在程序运行过程中是不可修改的。

18.在C语言中,若有一个字符数组char str[] = "Hello";,并且有一个字符指针char *p;,下列哪个操作可以将指针p指向字符串的末尾(即'\0'字符)? 

A. p = str; p += 5;

B. p = str; while(*p) p++;

C. p = str[5];

D. p = &str[5];

正确答案:B

解析:在C语言中,字符串是以空字符'\0'结尾的一维字符数组。要将指针p指向字符串的末尾,即空字符'\0'的位置,可以使用循环遍历字符串,直到遇到空字符为止。选项B中的p = str; while(*p) p++;正是这样的操作,它将指针p初始化为指向字符串的首字符,然后通过循环移动指针,直到指针指向空字符。选项A中的p = str; p += 5;虽然将指针移动到了数组的末尾之后的位置,但这并不是字符串的末尾,因为字符串的末尾是由空字符标识的。选项C中的p = str[5];是错误的,因为它将数组第六个元素(越界)的值赋给了指针p,而不是地址。选项D中的p = &str[5];也是错误的,同样是因为它将指针指向了数组的末尾之后的位置,而不是字符串的末尾。

19.在C语言中,若有一个指向整型的指针数组int *arr[5];,并且已经为数组的每个元素分配了动态内存,下列哪个操作可以正确地释放所有分配的内存? 

A. free(arr);

B. for(int i = 0; i < 5; i++) free(arr[i]);

C. free(*arr);

D. free(arr[0]);

正确答案:B

解析:在C语言中,malloc函数用于动态分配内存,而free函数用于释放动态分配的内存。对于指向整型的指针数组int *arr[5];,数组本身并不包含任何动态分配的内存,它只是包含了5个指向整型的指针。因此,不能直接使用free(arr);来释放数组本身,因为这并不会释放指针所指向的动态分配的内存。正确的做法是遍历指针数组,对每个元素使用free函数来释放它所指向的内存。选项B中的for(int i = 0; i < 5; i++) free(arr[i]);正是这样的操作。选项C中的free(*arr);只释放了数组第一个元素所指向的内存,而不是所有元素所指向的内存。选项D中的free(arr[0]);也只释放了数组第一个元素所指向的内存。

20.在C语言中,若有一个函数int func(int a, int b);,并且有一个指向函数的指针int (*p)(int, int);,下列哪个操作可以正确地通过指针调用函数func? 

A. p = func; (*p)(1, 2);

B. p = &func; p(1, 2);

C. *p = func; p(1, 2);

D. p = func; p(1, 2);

正确答案:A

解析:(本题为单选,但A和B都是正确的,选择最直接的答案A)在C语言中,可以通过指向函数的指针来调用函数。首先,需要定义一个指向函数的指针变量,并将函数的地址赋给它。然后,可以通过解引用指针或者直接使用指针变量来调用函数。选项A中的p = func; (*p)(1, 2);和选项B中的p = &func; p(1, 2);都是正确的操作。它们首先将函数的地址赋给了指针变量p,然后通过解引用指针(选项A)或者直接使用指针变量(选项B,这里省略了解引用操作符*,但在函数调用中这是允许的)来调用函数。选项C中的*p = func;是错误的,因为它试图将函数的地址赋给指针所指向的值,而不是指针本身。选项D中的p = func; p(1, 2);在大多数编译器中也是正确的,但严格来说,更好的风格是使用p = &func;来明确地将函数的地址赋给指针变量。

21.在C语言中,若有一个整型数组int arr[10];,且int *p = arr;,则下列表达式中不能表示数组元素arr[3]地址的是

A. p + 3

B. &arr[3]

C. arr + 3

D. p[3]

正确答案:D

解析:在C语言中,数组名arr和指针p都可以作为指向数组首元素的指针。因此,p + 3和arr + 3都表示数组第四个元素(即arr[3])的地址。&arr[3]也直接给出了arr[3]的地址。然而,p[3]表示的是指针p所指向的数组第四个元素的值,而不是地址。所以选项D是错误的。

22.关于字符指针和字符数组,以下说法错误的是

A. 字符数组可以直接用来存储字符串

B. 字符指针可以通过赋值指向一个字符串常量

C. 字符数组的名字是一个指针常量,其值不能改变

D. 字符指针变量的值可以改变,以指向不同的字符串

正确答案:C

解析:字符数组确实可以直接用来存储字符串,因为字符串在C中就是以字符数组的形式表示的,以空字符\0结尾。字符指针也可以被赋值为指向一个字符串常量,这是常见的用法。字符指针变量的值(即它所指向的地址)是可以改变的,这使得它非常灵活,可以指向不同的字符串。然而,字符数组的名字虽然可以被当作指针来使用(在大多数表达式中,数组名会被转换为指向数组首元素的指针),但它本身是一个常量,不能作为指针变量来被赋值或修改其指向。因此,选项C的说法是错误的。

23.在C语言中,若有一个函数void func(int *p);,并且有一个整型变量int a = 5;,下列哪个调用方式是正确的? 

A. func(a);

B. func(&a);

C. func(*a);

D. func(int *p = &a);

正确答案:B

解析:函数void func(int *p);期望一个指向整型的指针作为参数。整型变量a的值是5,但它本身不是一个指针。因此,直接将a作为参数传递给func是错误的(选项A)。&a是取变量a的地址,得到一个指向整型的指针,这正是func函数所需要的(选项B)。*a是解引用操作,它会尝试获取指针a所指向的值,但a不是一个指针,所以这是错误的(选项C)。选项D的语法也是错误的,因为函数调用时不能直接声明新的变量并初始化它作为参数。

24.在C语言中,若有一个指向整型的指针数组int *arr[5];,并且想要为数组的每个元素分配动态内存,并初始化它们为0,下列哪个操作是正确的? 

A. for(int i = 0; i < 5; i++) { arr[i] = (int*)malloc(sizeof(int)); *arr[i] = 0; }

B. for(int i = 0; i < 5; i++) { arr[i] = malloc(sizeof(int*)); *arr[i] = 0; }

C. for(int i = 0; i < 5; i++) { arr[i] = (int)malloc(sizeof(int)); *arr[i] = 0; }

D. for(int i = 0; i < 5; i++) { arr[i] = malloc(sizeof(int)); arr[i] = 0; }

正确答案:A

解析:在C语言中,malloc函数用于动态分配内存,并且它返回的是一个void*类型的指针,需要将其强制转换为适当的类型。对于指向整型的指针数组int *arr[5];,我们需要为每个元素分配一个整型大小的内存空间,并将分配的内存初始化为0。选项A中的代码正是这样做的:它使用malloc(sizeof(int))来分配内存,并将返回的void*类型的指针强制转换为int*类型,然后赋值给arr[i]。接着,使用*arr[i] = 0;来初始化分配的内存为0。选项B中的malloc(sizeof(int*))是错误的,因为它分配的是指针大小的内存,而不是整型大小的内存。选项C中的(int)malloc(sizeof(int))是错误的,因为malloc返回的是指针,不能直接被强制转换为整型。选项D中的arr[i] = 0;是错误的,因为它将指针变量arr[i]本身置为0,而不是它所指向的内存。

25.在C语言中,若有一个函数指针int (*p)(int, int);,并且有一个函数int add(int a, int b) { return a + b; },下列哪个操作可以正确地让函数指针p指向函数add,并通过p调用add函数? 

A. p = add; add(1, 2);

B. p = &add; p(1, 2);

C. *p = add; (*p)(1, 2);

D. p = add; (*p)(1, 2);

正确答案:B

解析:(本题为单选,但B和D都是正确的,选择最直接的答案B)在C语言中,函数名(如add)在大多数表达式中都会被当作指向该函数的指针。因此,我们可以直接将函数名赋值给函数指针变量,而不需要使用取地址操作符&(尽管在某些情况下使用&也是正确的)。选项B和D都正确地将函数add的地址赋给了函数指针p。然后,可以通过函数指针p来调用函数add,这可以通过直接调用p(1, 2)(选项B)或者通过解引用指针(*p)(1, 2)(选项D)来实现。选项A中虽然正确地让p指向了add,但没有通过p来调用add函数。选项C中的*p = add;是错误的,因为它试图将函数的地址赋给指针所指向的值,而不是指针本身。

26.在C语言中,若有一个指向字符的指针char *p;,并且想要让它指向字符串"Hello",下列哪个操作是正确的?

A. p = "Hello";

B. *p = "Hello";

C. p = 'H';

D. *p = 'H';

正确答案:A

解析:在C语言中,字符串常量(如"Hello")本身就是一个字符数组的首地址,可以被赋值给指向字符的指针。因此,选项A中的p = "Hello";是正确的,它让指针p指向了字符串"Hello"的首字符。选项B中的*p = "Hello";是错误的,因为*p表示指针p所指向的字符,而"Hello"是一个字符串常量,不能被赋值给一个字符。选项C中的p = 'H';是错误的,因为'H'是一个字符常量,而不是指针,不能被赋值给指向字符的指针。选项D中的*p = 'H';也是错误的,它试图将字符'H'赋值给指针p所指向的字符,但此时指针p并没有指向任何有效的内存地址,这会导致未定义行为。

27.在C语言中,若有一个函数int func(int a, int b);,并且想要定义一个指向该函数的指针p,下列哪个定义是正确的?

A. int *p(int, int);

B. int (*p)(int, int);

C. int *p = func;

D. int (*p) = func;

正确答案:B

解析:在C语言中,定义指向函数的指针时,需要指明函数的返回类型和参数类型。选项B中的int (*p)(int, int);正确地定义了一个指向返回类型为int,参数类型为两个int的函数的指针p。选项A中的int *p(int, int);定义了一个返回类型为指向int的指针,参数类型为两个int的函数,这不是我们想要的。选项C中的int *p = func;试图将函数func赋值给指向int的指针p,这是错误的,因为函数不能被赋值给指向基本数据类型的指针。选项D中的int (*p) = func;虽然看起来接近正确,但缺少了函数指针定义的括号,实际上这也是一个语法错误。

28.在C语言中,若有一个整型数组int arr[5] = {1, 2, 3, 4, 5};,并且有一个指向整型的指针int *p = arr;,下列哪个表达式不能正确地表示数组元素arr[2]?

A. *(p + 2)

B. p[2]

C. *(arr + 2)

D. arr[p + 2]

正确答案:D

解析:在C语言中,数组名在大多数表达式中都会被当作指向数组首元素的指针。因此,p和arr都可以作为指向数组首元素的指针来使用。选项A中的*(p + 2)和选项C中的*(arr + 2)都是通过指针运算来访问数组元素的,它们都正确地表示了数组元素arr[2]。选项B中的p[2]是数组下标运算的另一种写法,也正确地表示了arr[2]。然而,选项D中的arr[p + 2]是错误的,因为arr是数组名,不是指针变量,不能直接与整数或指针进行加法运算。正确的写法应该是*(p + 2)或p[2]。

29.在C语言中,若想要动态分配一个整型数组,数组的大小由用户输入决定,并且想要通过指针来访问这个数组,下列哪个步骤是错误的?

A. 定义一个指向整型的指针int *p;

B. 使用scanf函数获取用户输入的数组大小n

C. 使用malloc函数为数组分配内存,并将返回的指针赋值给p

D. 使用free函数释放内存后,仍然通过指针p访问数组元素

正确答案:D

解析:在C语言中,动态内存分配通常使用malloc函数来完成。选项A中定义了一个指向整型的指针p,这是正确的第一步。选项B中使用scanf函数获取用户输入的数组大小n,这也是必要的步骤。选项C中使用malloc函数为数组分配内存,并将返回的指针赋值给p,这是动态分配内存的正确方法。然而,选项D中的错误在于,在使用free函数释放内存后,仍然尝试通过指针p访问数组元素。这是不安全的,因为free函数释放了指针p所指向的内存,之后p变成了一个悬空指针(dangling pointer),它不再指向任何有效的内存区域。尝试通过悬空指针访问内存会导致未定义行为。

32.在C语言中,若有一个指向整型的指针数组int *arr[3];,并且想要为每个数组元素分配动态内存并初始化它们为0,1,2,下列哪个循环是正确的?

A. for(int i = 0; i < 3; i++) { arr[i] = (int*)malloc(sizeof(int)); *arr[i] = i; }

B. for(int i = 0; i < 3; i++) { arr[i] = malloc(sizeof(int*)); *arr[i] = i; }

C. for(int i = 0; i < 3; i++) { arr[i] = (int)malloc(sizeof(int)); *arr[i] = i; }

D. for(int i = 0; i < 3; i++) { int *p = malloc(sizeof(int)); arr[i] = p; *p = i; }

正确答案:A

解析:在C语言中,为指针数组的每个元素分配动态内存并初始化它们需要正确的内存分配和指针操作。选项A中的循环是正确的,它使用malloc(sizeof(int))来分配内存,并将返回的void*类型的指针强制转换为int*类型,然后赋值给arr[i]。接着,使用*arr[i] = i;来初始化分配的内存为i(0,1,2)。选项B中的malloc(sizeof(int*))是错误的,因为它分配的是指针大小的内存,而不是整型大小的内存。选项C中的(int)malloc(sizeof(int))是错误的,因为malloc返回的是指针,不能直接被强制转换为整型。选项D虽然也能达到目的,但它引入了一个不必要的中间变量p,而直接使用arr[i]更为直接和简洁。因此,选项A是最优解。

31.在C语言中,若有一个整型二维数组int arr[3][4];,并且想要通过指针来遍历这个数组的所有元素,下列哪个指针定义和循环是正确的?

A. int *p = arr; for(int i = 0; i < 12; i++) { printf("%d ", *(p + i)); }

B. int **p = arr; for(int i = 0; i < 3; i++) { for(int j = 0; j < 4; j++) { printf("%d ", *(*(p + i) + j)); } }

C. int (*p)[4] = arr; for(int i = 0; i < 3; i++) { for(int j = 0; j < 4; j++) { printf("%d ", (*(p + i))[j]); } }

D. int *p = &arr[0][0]; for(int i = 0; i < 3; i++) { for(int j = 0; j < 4; j++) { printf("%d ", *(*(p + i*4) + j)); } }

正确答案:C

解析:在C语言中,二维数组可以通过指向其第一行(或第一列,视情况而定)的指针来遍历。选项A中的指针定义虽然可以让p指向数组的首元素,但循环中直接按线性方式遍历会忽略数组的二维结构,导致访问越界或遗漏。选项B中的int **p = arr;是错误的,因为arr是一个指向整型二维数组(即包含4个整型元素的一维数组)的指针,而不是指向指针的指针。选项C中的int (*p)[4] = arr;正确地定义了一个指向包含4个整型元素的一维数组的指针,然后通过两层循环正确地遍历了二维数组的所有元素。选项D中的指针定义虽然正确,但循环中的指针运算*(p + i*4) + j依赖于数组的内存布局,虽然在这个特定情况下可能工作,但不是一种通用或推荐的方法。

32.在C语言中,若有一个字符数组char str[] = "hello";,并且想要通过字符指针来修改字符串的内容,下列哪个操作是正确的?

A. char *p = str; p[0] = 'H';

B. char *p = "hello"; p[0] = 'H';

C. char *const p = str; p[0] = 'H';

D. const char *p = str; p[0] = 'H';

正确答案:A

解析:在C语言中,字符串字面量(如"hello")通常存储在只读内存段中,不能通过指针修改其内容。选项A中的char *p = str;定义了一个指向字符数组str的指针,该数组是可修改的,因此p[0] = 'H';能够正确地修改字符串的第一个字符。选项B中的char *p = "hello";定义了一个指向字符串字面量的指针,尝试修改p[0]会导致未定义行为(通常是程序崩溃)。选项C和D中的const关键字表明指针或指针所指向的内容是常量,不能修改,因此它们都是错误的。

33.在C语言中,若有一个函数void func(int *arr, int n);,该函数接受一个指向整型数组的指针和数组的大小,并在函数内部修改数组的元素。下列哪个函数调用是正确的?

A. int arr[5] = {1, 2, 3, 4, 5}; func(arr, 5);

B. int *arr = {1, 2, 3, 4, 5}; func(arr, 5);

C. int arr[5]; func(&arr, 5);

D. int *arr = malloc(5 * sizeof(int)); func(arr, 5); (假设已包含必要的头文件和内存分配检查)

正确答案:A

解析:在C语言中,数组名在大多数情况下会被当作指向数组首元素的指针。选项A中的int arr[5] = {1, 2, 3, 4, 5};定义了一个整型数组,并将数组名arr(即指向数组首元素的指针)和数组大小5作为参数传递给func函数,这是正确的。选项B中的int *arr = {1, 2, 3, 4, 5};是错误的,因为这里尝试使用初始化列表来初始化一个指针,而不是数组。选项C中的func(&arr, 5);是错误的,因为&arr是指向整个数组的指针(类型为int (*)[5]),而不是指向数组首元素的指针。选项D虽然在使用动态内存分配时是合法的,但题目中并没有要求使用动态内存分配,且该选项没有提供初始化数组元素的值,因此不是最佳答案。

34.在C语言中,若有一个指向整型的指针int *p;,并且想要让它指向一个整型变量int x = 10;,同时希望通过指针来修改x的值,下列哪个操作是正确的?

A. *p = x;

B. p = &x; *p = 20;

C. *p = &x;

D. p = x; *p = 20;

正确答案:B

解析:在C语言中,指针变量需要被赋予一个有效的内存地址才能通过它来访问或修改该地址处的值。选项A中的*p = x;尝试将x的值赋给p所指向的内存地址,但此时p并没有指向任何有效的内存地址,这会导致未定义行为。选项B中的p = &x;首先让p指向变量x的地址,然后通过*p = 20;正确地修改了x的值。选项C中的*p = &x;是错误的,因为这里尝试将变量x的地址赋给p所指向的内存地址处的值,这是不合法的。选项D中的p = x;是错误的,因为这里尝试将变量x的值(而不是地址)赋给指针p,然后通过*p = 20;尝试修改一个未知地址处的值,这同样会导致未定义行为。

35.在C语言中,若有一个指向整型数组的指针数组int *arrPtr[3];,并且想要让arrPtr[0]、arrPtr[1]和arrPtr[2]分别指向三个不同的整型数组,下列哪个操作是正确的?

A. int a[2] = {1, 2}; int b[2] = {3, 4}; int c[2] = {5, 6}; arrPtr = {a, b, c};

B. int a[2] = {1, 2}; int b[2] = {3, 4}; int c[2] = {5, 6}; arrPtr[0] = a; arrPtr[1] = b; arrPtr[2] = c;

C. int *a = {1, 2}; int *b = {3, 4}; int *c = {5, 6}; arrPtr[0] = a; arrPtr[1] = b; arrPtr[2] = c;

D. int a[2]; int b[2]; int c[2]; arrPtr[0] = &a; arrPtr[1] = &b; arrPtr[2] = &c;

正确答案:B

解析:在C语言中,指针数组是一个包含指针的数组。选项A中的arrPtr = {a, b, c};是错误的,因为不能像这样直接给指针数组赋值。选项B中的操作是正确的,它分别让arrPtr[0]、arrPtr[1]和arrPtr[2]指向了三个不同的整型数组a、b和c的首元素。选项C中的int *a = {1, 2};等语句是错误的,因为这里尝试使用初始化列表来初始化指针变量,而不是数组。选项D中的arrPtr[0] = &a;等语句是错误的,因为&a是指向整个数组的指针(类型为int (*)[2]),而不是指向数组首元素的指针(类型为int *)。

36.在C语言中,若有一个函数指针void (*funcPtr)(int);,并且想要让它指向一个接受整型参数并返回void的函数void myFunction(int x);,下列哪个操作是正确的?

A. funcPtr = myFunction;

B. *funcPtr = myFunction;

C. funcPtr = &myFunction;

D. void (*funcPtr)(int) = myFunction;

正确答案:A

解析:在C语言中,函数名在大多数情况下会被当作指向该函数的指针。因此,选项A中的funcPtr = myFunction;是正确的,它将函数指针funcPtr指向了函数myFunction。选项B中的*funcPtr = myFunction;是错误的,因为这里尝试修改函数指针所指向的函数,这是不允许的。选项C中的funcPtr = &myFunction;虽然也是正确的,但在C语言中,取函数名的地址和直接使用函数名作为指针是等价的,所以通常省略取地址符&。选项D是一个函数指针的定义,并不是赋值操作,所以不符合题目要求。

37.在C语言中,若有一个指向字符的指针数组char *strArr[3];,并且想要让它存储三个字符串"apple"、"banana"和"cherry",下列哪个操作是正确的?

A. strArr = {"apple", "banana", "cherry"};

B. strArr[0] = "apple"; strArr[1] = "banana"; strArr[2] = "cherry";

C. *strArr[0] = "apple"; *strArr[1] = "banana"; *strArr[2] = "cherry";

D. strcpy(strArr[0], "apple"); strcpy(strArr[1], "banana"); strcpy(strArr[2], "cherry");

正确答案:B

解析:在C语言中,指针数组是一个数组,其元素都是指针。选项A中的strArr = {"apple", "banana", "cherry"};是错误的,因为不能像这样直接给指针数组赋值。选项B中的操作是正确的,它分别让strArr[0]、strArr[1]和strArr[2]指向了三个字符串字面量的首字符。选项C中的*strArr[0] = "apple";等语句是错误的,因为这里尝试将字符串字面量的地址赋给指针所指向的字符,这是不合法的。选项D中的strcpy(strArr[0], "apple");等语句也是错误的,因为strArr[i]还没有指向有效的内存区域,直接使用strcpy会导致未定义行为。

38.在C语言中,若有一个整型变量int x = 10;,并且想要通过指向它的指针来修改它的值,下列哪个操作是正确的?

A. int *p; *p = 20;

B. int *p = &x; *p = 20;

C. int *p = x; *p = 20;

D. int *p; p = 20;

正确答案:B

解析:在C语言中,要通过指针修改变量的值,首先需要让指针指向该变量的地址,然后通过解引用指针来修改值。选项A中的int *p; *p = 20;是错误的,因为此时p是一个未初始化的指针,解引用未初始化的指针会导致未定义行为。选项B中的int *p = &x; *p = 20;是正确的,它首先让p指向变量x的地址,然后通过*p = 20;修改了x的值。选项C中的int *p = x;是错误的,因为这里尝试将变量x的值赋给指针p,而不是变量x的地址。选项D中的int *p; p = 20;也是错误的,因为这里尝试将整数20赋给指针p,而不是某个变量的地址。

39.在C语言中,若有一个指向整型的指针int *p;,并且想要通过它来访问一个整型数组int arr[5] = {1, 2, 3, 4, 5};中的元素,下列哪个操作是正确的?

A. p = arr; for(int i = 0; i < 5; i++) { printf("%d ", p[i]); }

B. p = &arr; for(int i = 0; i < 5; i++) { printf("%d ", *(p + i)); }

C. p = arr[0]; for(int i = 0; i < 5; i++) { printf("%d ", *(p + i)); }

D. p = &arr[0]; for(int i = 0; i < 5; i++) { printf("%d ", p[i*sizeof(int)]); }

正确答案:A

解析:在C语言中,数组名在大多数情况下会被当作指向数组首元素的指针。选项A中的p = arr;让p指向了数组arr的首元素,然后通过p[i]或*(p + i)(两者等价)来访问数组中的元素,这是正确的。选项B中的p = &arr;是错误的,因为&arr是指向整个数组的指针(类型为int (*)[5]),而不是指向数组首元素的指针(类型为int *)。选项C中的p = arr[0];是错误的,因为这里尝试将数组第一个元素的值赋给指针p,而不是数组首元素的地址。选项D中的p[i*sizeof(int)]是错误的,因为指针的索引操作已经隐含了根据指针类型进行偏移的操作,不需要再乘以sizeof(int)。

40.在C语言中,若有一个指向整型数组的指针int (*p)[5];,并且想要让它指向一个整型数组int arr[5] = {1, 2, 3, 4, 5};,同时想要通过该指针来访问数组中的元素,下列哪个操作是正确的?

A. p = arr; for(int i = 0; i < 5; i++) { printf("%d ", (*p)[i]); }

B. p = &arr; for(int i = 0; i < 5; i++) { printf("%d ", p[i]); }

C. *p = arr; for(int i = 0; i < 5; i++) { printf("%d ", p[i]); }

D. p = arr; for(int i = 0; i < 5; i++) { printf("%d ", p[i][0]); }

正确答案:A

解析:在C语言中,int (*p)[5];定义了一个指向包含5个整型元素的数组的指针。选项A中的p = arr;让p指向了数组arr,然后通过(*p)[i]来访问数组中的元素,这是正确的。选项B中的p = &arr;虽然让p指向了数组arr的地址,但p[i]的访问方式是错误的,因为p是指向整个数组的指针,而不是指向数组元素的指针。选项C中的*p = arr;是错误的,因为这里尝试将数组arr的值赋给p所指向的数组,这是不合法的。选项D中的p[i][0]是错误的,因为p[i]已经是指向数组的指针了,不需要再进行一次索引操作。


下载详情底部广告位

文章评论

加载中~