C语言刷题(Day2~Day5)
2023.03.26~2023.04.02
一、内容来源
1、题目来源
————————————————
牛客网 刷题部分 C语言
二、疑惑知识点小结
Day2
1、C程序书写格式比较自由,一个语句可以分写在多行上。(比如说 while 语句,等可以分多行进行编写)
2、为什么 语句#include< stdlib.h >是正确的,而且程序编译速度比#include “stdlib.h”要快?
答: include <file> //在标准库及默认搜索目录中寻找将要 include 的文件 ;
include "file" //先在当前目录中搜索文件,然后再到默认搜索目录中搜寻。
3、printf 函数的返回值为:函数返回输出的字符串的长度,但是不包括结束符‘\0’
4、free 释放掉一个指针内容后,指针还会指向原来的那块地址,需要我们设置p = NULL;如果不手动设置 p = NULL,此时P就变成了野指针。
1)野指针:表示的是保存了没有使用到的指针地址。
5、32位机中,无论是什么指针,它的长度都是四字节。
6、函数的默认值 函数的默认值不允许为局部变量 (什么讲究?)【】
7、new delete 与malloc free 的联系与区别 是什么?
1)new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的
构造函数,初始化成员变量,最后返回自定义类型指针。delete先调 用析构函数,然后调用operator
delete函数释放内存(通常底层使用free实现)
malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和
析构工作
8、内联函数有什么作用?
1)可以把它作为一般的函数一样调用,但是由于内联函数在需要的时候,会像宏一样展开,所以执行速度
确比一般函数的执行速度要快。当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,
如果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式调用函数。(换句话说
就是,你使用内联函数,只不过是 向编译器提出一个申请,编译器可以拒绝你的申请)这样,内联
函数就和普通函数执行效率一样了
2)当只有一个地方调用了内联函数时,编译器会在调用处将内联函数展开,这样就少了函数的跳转指令,
栈的扩展指令,因此可能减小文件的大小
Day3
1、关于多态性的说法
1)多态性是指同名函数对应多种不同的实现
2)重载方式包含函数重载和运算符重载
3)多态性表现为静态和动态两种方式
2、scanf ()函数中, %d 对应的参数是整数型地址, %c 对应参数为 char 型地址;如果输入地址有多个,
应该用逗号隔开
3、函数原型声明语句 :形式参数,只需要指定类型,名称可有可无
Day4
1、程序中自动转换是从位数少的转换为位数多的
2、指针变量若赋值一个字符串,则会得到这个字符串的首地址
3、联合体的大小为联合元素内最大元素的字节数
4、默认参数匹配时,按照靠前原则
int fun( int i = 1, intj = 2) { return (i + j); }
则fun(3)的值为:5
5、二维数组定义规范:定义字符型数组时不允许直接使用“字符常量”的方式赋初值,C语言规定,二维数组定义时
不允许省略第二维的长度
Day5
无
三、错题记录
Day2
1.代码段char
a[] = {'a'
,'b'
,'c'
};char` `b[] = {
“abc”``};
数组a和数组b占用的内存空间大小不一样。请问这句话的说法是正确的吗?
正确,大小不一样。因为数组b中 还有一个结束符 会占据一个字节
2.以下程序中,while循环的循环次数是()
int i=0;
while (i<10) {
if(i<1) continue;
if(i==5) break;
i++;
}
正确答案为:死循环,不能缺点给次数,因为i的初始值为0,当进入循环体中之后,if后面的条件 i<1 成立
之后,i不会加加,会一直循环 continue 语句
3.下面代码段的输出为() #define MOD(x,y) x%y int` `a = 13, b = 94;
printf(
“%d\n”``, MOD(b,a + 4));
正确输出为:7 需要注意的是宏定义只是简单的替换,不涉及运算符的计算
4.以下选项中,对基本类型相同的指针变量不能进行运算的运算符是()
A +
B -
C =
D ==
正确答案:A 因为两个相同类型的指针变量进行相加的话,很可能会出现指针越界的情况,所以不允许相加
5.下面代码的执行结果是() #include <stdio.h>
int` `main(
void)
{
char` `*p[] = {
“TENCENT”,
“CAMPUS”,
“RECRUITING”};
char` `**pp[] = {p + 2, p + 1, p};
``char
***ppp = pp;
printf
("%s "
, **++ppp);printf(
“%s”, *++*++ppp);
return` `0;
}
A CAMPUS RECRUITING
B RECRUITING CAMPUS
C CAMPUS CAMPUS
D RECRUITING RECRUITING
解析如下:
从题干当中,我们可以画出这样的一个图,这样就比较直观的看出了p,pp,ppp都指向哪里了,关键是最后两个printf语句。
(1)printf(“%s”,**++ppp);即,ppp当前所指向的位置,再往下移一个位置,即pp的位置2,而pp的位置2指向的是p的位置2,p的位置2指向的是CAMPUS,所以先输出CAMPUS
(2)printf(“%s”,++++ppp);这个语句等价于 printf(“%s”,++(++ppp));所以我们首先看,++ppp,第一个printf语句中ppp已经指向了pp的位置2,所以再往下移一个,指向了pp的位置3,而(*++ppp)则代表pp位置3所指向的内容,即p的位置1(pp的位置3指向的是p的位置1),在此基础上前面再加上一个++,则代表指针p在位置1的基础上再往下移动,即指针p的位置2,而p的位置2所指向的内容是CAMPUS,所以第二行输出的也是CAMPUS。
所以正确答案是:CAMPUS CAMPUS
Day3
1、下面3段程序代码的效果一样吗?
intb;(1)
constinta = &b;(2)
intconsta = &b;(3)
int*``const
a = &b;
A (2)=(3)
B (1)=(3)
C (1)=(2)
D 都不一样
E 都一样
解析:
const在*的左边,则指针指向的变量的值不可直接通过指针改变(可以通过其他途径改变);在*的右边,则
指针的指向不可变。简记为"左定值,右定向"。
2、下述程序的输出是 #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``;
}
A ink 【√】
B pink
C white
D hite
解析:如下图所示
Day4
1、extern “C” 的作用:
extern "C" 的作用是为了能够正确的实现 C++ 代码调用 C 语言代码。加上 extern "C" 后,会指示编译器这
部分代码按照 C 语言(而不是 C++)的方式进行编译。由于 C++ 支持函数重载,因此编译器编译函数的过程中
会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译 C 语言
代码的函数时不会带上函数的参数类型,一般只包括函数名。 这个功能十分有用处,因为在 C++ 出现以前,很
多代码都是 C 语言写的,而且很底层的库也是 C 语言写的,为了更好的支持原来的 C 代码和已经写好的
C 语言库,需要在 C++ 中尽可能的支持 C,而 extern "C" 就是其中的一个策略。
2、字符串数组 输出数组名 就是输出的一个字符串首地址,也就能直接输出其中的字符串了
3、fseek(fp, 0, SEEK_END);
n = ftell
(fp);
函数 ftell 用于得到文件位置指针当前位置相对于文件首的偏移字节数。
4、print()函数是一个类的常成员函数,它无返回值,下列表示中正确的是
A const void print();
B void const print();
C void print() const; 【√】
D void print(const);
解释:链接:https://www.nowcoder.com/questionTerminal/0f84a042640648e793bededd5956690d
来源:牛客网
常成员函数含义是通过该函数只能读取同一类中的数据成员的值,而不能修改它。
规则:
1.常成员函数不能更新对象的数据成员
2.当一个对象被声明为常对象,则不能调用该类中的非const成员函数
常成员函数格式:
类型说明符 函数名(参数表)const;
int GetX() const; //声明常成员函数
5、使用C语言将一个1G字节的字符数组从头到尾全部设置为字’A’,在一台典型的当代PC上,需要花费的CPU时间的数量级最接近
解析:
执行1条语句约1ns即10的-9次方秒,1G=1024M=1024*1024k=1024*1024*1024byte,每次赋值1byte都要执行
一次语句,故至少花费1024*1024*1024*10^-9=1.073741824s
Day5
1.C语言中,若有int a[5]={12,34,56,78,90},*p=a;则 *p++==13.
解析:
*p++ 相当于 *(p++) 是指针先加1,再进行解引用,相当于是地址指向34的位置,在进行解引用即为34.
考点:操作符的优先级高低问题
2.下面代码的输出()
int main() {
int` `a[5] = {1, 2, 3, 4, 5};
intptr = (int
)(&a + 1);
printf
("%d, %d"
, *(a + 1), *(ptr - 1));
``return
0;
}
答案:2,5
解析:
a 为 int 型数组首地址,数组长度为 5,a + 1 表示 a[1] 的地址。
&a 可以理解为表示一个列数为 5 的 int 型二维数组的首地址,那么 &a + 1 表示列为 5 的 int 型二维数组
第 1 行首地址,然后转为 int 型指针赋值给 ptr,可以理解为 ptr 为 a[5] 的地址(可以这么理解,实际
不存在 a[5]),
ptr - 1 即为 a[4] 的地址
3.若有int c;,则while(c=getchar());是正确的 C 语句。请问这句话的说法是正确的吗?
c =getchar() 等号运算符的返回值是获得的字符。这样,当获得的字符不是\0时,则一直循环。
直到得到\0,退出循环
4.下面程序输出结果为()
class
A {
};
int
main() {
printf
("%d\n"
, sizeof
(class` `A));
return
0;
}
A 0
B 1
C 4
D 8
正确答案:B 空类的大小原本是0,但是为什么实际上是1,主要的一个中心思想是在强调:
任何相同类的不同对象应该拥有不同的地址。
5.空指针是指
A 所指向的空间位置未存放任何数据的指针
B 所指向的空间位置存放着数据0的指针
C 所指向的空间位置可用于存放任何类型数据的指针
D 所指向的空间位置就是地址0的指针
正确答案:D
空指针是一个特殊的指针值。 空指针是指可以确保没有指向任何一个对象的指针。通常使用宏定义NULL来
表示空指针常量值。NULL就代表系统的0地址单元 空指针确保它和任何非空指针进行比较都不会相等,因此
经常作为函数发生异常时的返回值使用
6.以下代码编译有错误,哪个选项能解决编译错误?【???】
class
A {
public
:
int` `GetValue()
const
{
vv = 1;
return
vv;
}
private:
int
vv;
};
A 改变成员变量"vv"为"mutable int vv"
B 改变成员函数"GetValue"的声明,以使其不是const的
C 都不能修复编译错误
D 都可以修复编译错误
正确答案:D
普通成员函数后面加上 const 修饰,就是常函数。
常函数中的 this 指针是常指针,不能在常函数中对成员变量进行修改,只能读取;
如果想要在常函数中对成员变量进行修改,可以在成员变量前加上 mutable 关键字进行修饰;
常函数可以被普通对象或者常对象调用,但是常对象只能调用常函数,常对象只能读成员
7.当调用函数时,实参是一个数组名,则向函数传送的是()【原题为多选,但是实际只有单选】
A 数组的长度
B 数组的首地址
C 数组每一个元素的地址
D 数组每个元素中的值
正确答案:B
8.开发C代码时,经常见到如下类型的结构体定义:
typedef
struct
list_t{struct` `list_t *next;
struct
list_t *prev;char` `data[0];
}list_t; 最后一行char data[0];的作用是?
A 方便管理内存缓冲区
B 减少内存碎片化
C 标识结构体结束
D 没有作用
正确答案:AB
解析:看不懂char data[0];请去百度 柔性数组,它只能放在结构体末尾,是 申明一个长度为0的数组,
就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,因为数组名本身
不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名
永远都不会是指针! ),但对于这个数组的大小,我们可以进行动态分配 请仔细理解后半部分,对于
编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,
代表一个不可修改的地址常量! 对于0长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包
等等: 注意:构造缓冲区就是方便管理内存缓冲区,减少内存碎片化,它的作用不是标志结构体结束,而是
扩展 柔性数组是C99的扩展,简而言之就是一个在struct结构里的标识占位符(不占结构struct的空间)