C语言练习题-细碎知识点

每道练习题涉及的知识点

在这里插入图片描述答案:5 7
涉及知识点:局部变量和全局变量

1、局部变量
定义在函数内部的变量称为局部变量,它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。
2、全局变量
在所有函数外部定义的变量称为全局变量,它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。
3、局部变量与全局变量的区别
1)局部变量是声明在块或者函数内部的变量。局部变量的作用域局限于该块或者函数。局部变量如果没有初始化,将包含垃圾数据。
2)全局变量是在所有块和函数之前声明的变量。全局变量对所有在它之后声明的函数有效。全局变量有默认值初始化,如0。
注意:如果要调用另外一个文件中的全局变量,如果再声明一个同名的全局变量,那么编译器会因为重名报错,这个时候就要使用extern变量。extern声明告诉编译器这个变量的定义在其他文件中,所以并不会为它分配内存。
4、静态局部变量和静态全局变量区别
1)非静态全局变量的作用域是整个源程序 ,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
2)静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。

在这里插入图片描述
答案:A
涉及知识点:文件
本题考查预处理中文件包含的概念,包含文件中可以包含其他文件, B 选项错误, #include 可以出现在程序文件的中间, C 选项错误,包含文件被修改了,包含该文件的源程序必须重新进行编译和连接。

在这里插入图片描述答案:D
涉及知识点:运算符
~是位运算符,意义是 按位非(NOT)
按位非也叫做补,一元运算符NOT“~”是对其运算数的每一位取反。

仅用于整数值
反转位,即0位变为1位,1变成0
在所有情况下〜x等于(-x)- 1

&按位与
|按位或 ~按位取反 ^按位异或 >>右移 >>>无符号右移 <<左移

在这里插入图片描述
答案:5次
涉及知识点:for循环的判断条件

for循环的判断条件为赋值,i = j,当且仅当 i = 0时,循环结束,即结束条件是 j = 0;
接下来我们来看for循环:
在这里插入图片描述
在这里插入图片描述
答案:a[1][1]
涉及知识点:指针

int a[3][2]={1,2,3,4,5,6}产生的结果是
a[0][0]=1,a[0][1]=2,a[1][0]=3,a[1][1]=4,a[2][0]=5,a[2][1]=6
根据数组的表示法,数组名可以指代数组整体,还可以指代数组头元素位置
也就是说a[0]就是表示1,2中的那个1的位置,a[1]就表示3,4中3的位置,类推a[2]指的是5的位置
*p[3]是声明一个整形指针的数组,也就是说是三个p,每个p都是指向整数的
p[0]=a[1]就是相当于p[0]=&a[1][0],也就是让p[0]指向3的位置
--------------------以上是题设的内容-----------------------
p[0]+1,根据指针的用法,指针进行加减操作,就是让指针在内存中前后移动
那么p[0]原来指向3的位置,p[0]+1就是让指针后移,那么就是指到了4的位置上
而 * (指针),表示的是指针所指位置上的实际变量,即 * (4的位置)那么就是4了,也就是a[1][1]
*p[3]是指针数组,每一个元素都是一个指针。p[0]指向a[1]行,p[0]+1指向下一个元素a[1][1]

在这里插入图片描述答案:程序崩溃
GetMemory虽然在堆上申请了内存空间,但是并未将地址赋值给str。str的值仍然为0,在进程地址空间中地址0为系统保留地址空间。
GetMemory(char *p);这里 *p是形参,是局部变量
不能讲malloc申请的地址指针返回,造成内存泄露
更严重的是执行GetMemory(str);后str依然为NULL
执行strcpy(str, ‘hello world’);就会出错
在这里插入图片描述
在这里插入图片描述答案:E G

A选项中,fscanf的原型是
int fscanf(FILE *stream, const char *format, …)
其中 stream 指向 FILE 对象的指针,该 FILE 对象标识了流,标准输入流是STDIN,因此fscanf可以从标准输入流中读取数据,A错误
B选项中,fopen的原型是
FILE *fopen(const char *filename, const char *mode)
它返回一个FILE结构指针,其中包含了对所打开流进行操作的全部信息,包括文件描述符。当执行程序时,STDIN STDOUT STDERR会自动打来,无需调用fopen打开,B错误
C选项中,如果没有明确地调用函数fclose,则操作系统通常在程序执行结束的稍后关闭文件。但是,这样可能会带来一些难以预料的问题,所以一定要注意在使用结束之后关闭文件。所以感觉C应该是对的,可能答案认为不是那么必须吧
D选项中,可以通过fseek函数定位流stream的文件位置,以whence为起点,偏移offset,因此无需关闭文件再打开,D错误
int fseek(FILE *stream, long int offset, int whence)
E选项中,fprintf原型为
int fprintf(FILE *stream, const char *format, …)
将stream写为STDOUT即可将数据写入标准输出流,E正确
F选项中,fseek的whence参数能够设置为SEEK_SET(文件的开头)SEEK_CUR(文件指针的当前位置)SEEK_END(文件的末尾),F错误
G选项中,随机存取文件是将记录散列在存取介质上的,可以自己定位想要读的文件内容的指针位置,不必从头查找,G正确

在这里插入图片描述
答案:死循环
其实这道题想要考察的是char型的表示范围:-128~127。num永远都到不了255。

在这里插入图片描述
答案:可以顺序存取,也可以随机存取
顺序存取:当“打开”文件进行读或写操作时总是从文件的开头开始,从头到尾顺序读或写。
直接存取:又称随机存取文件,可以通过调用C语言的库函数来指定开始读(写)的字节号,然后直接对此位置上的数据进行读或写操作

在这里插入图片描述
答案:110000(二进制)

<<是左移运算符的意思,左移运算符是用来将一个数的各二进制位全部左移若干位。
这里可以理解为把3化为2进制,然后统一左移4位。
3的二进制比如 0011 左移4位 110000 = 48

在这里插入图片描述
答案:
*(p[0] +2)

数组指针(也称行指针)
定义 int (p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。
如要将二维数组赋给一指针,应这样赋值:
int c[4][5];
int (p)[5]; //该语句是定义一个数组指针,指向含5个元素的一维数组。
p=c; //将该二维数组的首地址赋给p,也就是c[0]或&c[0][0]
p++; //该语句执行过后,也就是p=p+1;p跨过行c[0][]指向了行c[1][] * (p[0]+2);//等价于
(
(p+0)+2),表示a[0][2];
数组指针
1.&a[i][j] 数组元素a[i][j]的地址
2.&a[i] 数组元素a[i][0]的地址
3.a[0]+j 数组元素a[0][j]的地址
4.((a+i)+j) 数组元素a[i][j]的地址
5.*(a[i]+j) 数组元素a[i][j]的地址

小插曲知识点:

  1. 字符常量有两种:
    一种是普通字符,即用单撇号括起来的一个字符,如’b’ ,‘y’,‘?’。字符常量在储存在计算机的储存单元中时,是以其代码(一般采用ASCII代码)储存的。
    另一种是转义字符,即特殊字符常量。转移字符是C语言中表示字符的一种特殊形式,其含义是将反斜杠后面的字符转换成另外的意义。
    另外还可以用字符的ASCII码表示,即用反斜符()开头,后跟字符的ASCII码,这种方法也称为转义序列表示法,具体方法是:有两种形式:
    一种是用字符的八进制ASCII码,表示为:\0dd.这里,0dd是八进制值(0可以省略)。
    另一种使用字符的十六进制ASCII码值,表示为 \xhh或Xhh 这里hh是两位十六进制值。
    如:‘A’ ,’\101’ 和 '\x41’都表示同一个字符常量。

使用单撇号括起一个字符的形式即字符常量。使用字符常量需要注意以下几点:
(1)字符常量只能用单撇号括起来,不能使用单引号或其他括号。
(2)字符常量中只能包括一个字符,不能是字符串。
(3)字符常量是区分大小写的。
(4)单撇号只是界限符,不属于字符常量中旳一部分,字符常量只能是一个字符,不包括单撇号。
(5)单撇号里面可以是数字、字母等C语言字符集中除’和\以外所有可现实的单个字符,但是数字被定义为字符之后则不能参与数值运算。

2.C中的结构体没有函数 但是C++的结构体可以有函数;这是C与C++结构体的区别。
C++的结构体可以被类取代,因为类相对于结构体 具有封装性等优势。
C++中结构体与类的区别:
结构体中的成员访问权限不声明时候默认是 公开的;而类 是私有的

在这里插入图片描述
4.
printf可以使用使用格式控制串“%o”、“%X”分别输出八进制整数和十六进制整数,并使用修饰符“#”控制前导显示
printf可以使用使用格式控制串“%md”输出域宽为m的十进制整数。
小数在内存中有可能不能精确保存

5.C语言主函数可以位于其他函数定义之后;不可以嵌套定义函数,但是可以嵌套调用函数。
6.strcpy注意点
在这里插入图片描述strcpy( str1, str2);str1的长度不够,会怎么样呢?
似乎拷贝成功,但这并不意味会自动把str1长度增加, 反而会把后面的其它数据破坏了
推荐使用strncpy
原型:char *strncpy(char *dest, char *src, int n);
用法:#include
功能:把src所指由NULL结束的字符串的前n个字节复制到dest所指的数组中。
说明:如果src的前n个字节不含NULL字符,则结果不会以NULL字符结束。如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。
strncpy(str1, str2, strlen(str1));第三个参数一定要小于等于第一个参数的实际长度,保证拷贝在str1自己的空间内,但是,strlen(str1)并不一定就是缓冲区的实际长度,该函数测量到’\0’为止,如果str1第一个字节就是0,那么什么都拷贝不进去

继续练习题

在这里插入图片描述
答案:BCD

函数指针的定义格式为函数类型(*指针变量名)(形参列表)

在这里插入图片描述
答案:CD

通过指针调用函数的两种形式:
1、ret = (p)();
2、ret = p();
对函数指针赋值的两种形式:
1、pf = &func;
2、pf = func;
关于D答案:
要正常使用f1应该使用( * f1)(s),与f1(s)效果相同。
* f1(s)中()的优先级比
高,()先与f1(s)结合,返回结果是char,*f1(s)是对返回结果解引用。
在这里插入图片描述在这里插入图片描述

答案:D
关系运算符都满足左结合律,从左到右比较
移位运算符满足左结合律,逗号运算符从左到右计算
赋值运算符和sizeof运算符满足右结合律
a>b>c这里是从左到右比较的,先比较a>b 这个值是真的,是1。然后拿1和C比较1>c是假的,值是0。所以D=0。

在这里插入图片描述
答案:1
首先求非运算,得0&&0||1 然后求与运算,得0||1 最后求或运算,得1

设有语句 char a = ‘\72’; 则变量 a ()包含几个字符?
答案:一个字符

在这里插入图片描述
在这里插入图片描述
答案:无法确定

函数fun()的参数为值传递,在函数体内的操作不能对传入的值进行修改,所以无法确定
正确解法:
1.将fun(int a,int b,int c)改为fun(int a,int b,int * c) 或者是 fun(int a,int b,int & c),即指针或者引用传递
2.加返回值 int fun(int a,int b,int c)

在这里插入图片描述
答案:错
case后面没有break,输出A后不退出。继续往下执行输出B

在这里插入图片描述答案:16 20,16 20
在这里插入图片描述
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐。每个特定平台上的编译器都有自己的默认“对齐系数”(32位机一般为4,64位机一般为8)。我们可以通过预编译命令#pragma pack(k),k=1,2,4,8,16来改变这个系数,其中k就是需要指定的“对齐系数”;也可以使用#pragma pack()取消自定义字节对齐方式。
struct 或者 union 成员对齐规则如下:

  1. 第一个数据成员放在offset为0的地方,对齐按照对齐系数和自身占用字节数中,二者比较小的那个进行对齐;
  2. 在数据成员完成各自对齐以后,struct或者union本身也要进行对齐,对齐将按照对齐系数和struct或者union中最大数据成员长度中比较小的那个进行;
    先局部成员对齐,然后再全局对齐。

在这里插入图片描述答案:20
在这里插入图片描述
在这里插入图片描述答案:A

后缀++ 和-- 操作符本质上比前缀一目操作的优先级高, 因此p++ 和(p++) 等价, 它自增p 并返回p 自增之前所指向的值。要自增p 指向的值, 使用(*p)++, 如果副作用的顺序无关紧要也可以使用++*p。

在这里插入图片描述答案:B

函数调用把该函数的返回值作为实参进行传送,因此只要该函数有返回值即可。所以有返回值的函数可以出现在一个表达式里

在这里插入图片描述答案:B

题中三种数据类型的精度从低到高为int->float->double,从低到高的转换通常可以保持其值不变,I和III正确,而从高到低的转换可能会有数据的舍入,从而损失精度。对于II,先将float型的f转换为int型,小数点后的数位丢失,故其结果不为真。对于IV,初看似乎没有问题,但浮点运算d+f时需要对阶,对阶后f的尾数有效位被舍去而变为0,故d+f仍然为d,再减去d后结果为0,故IV结果不为真。此外,根据不同类型数据混合运算的“类型提升”原则,在IV中,等号左端的类型为double型,结果不为真。

在这里插入图片描述
答案:正确
数组未定义的默认为0,实际为3*3的数组
第零行为3 5 0第一行8 9 0第三行12 35 0
for循环进行后为0+9+12

在这里插入图片描述
答案:B
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值