寒假作业Day 06
一、选择题
1、关于内存管理,以下有误的是( )
A: malloc在分配内存空间大小的时候是以字节为单位
B: 如果原有空间地址后面还有足够的空闲空间用来分配,则在原有空间后直接增加新的空间,使得增加新空间后的空间总大小是:newSize
C: 如果原有空间地址后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存,并把先前内存空间中的数据复制到新的newSize大小的空间中,然后将之前空间释放
D: free函数的作用是释放内存,内存释放是标记删除,会修改当前空间的所属状态,并且会清除空间内容
A正确,比如创建一个四个int类型的数组就可以这样创建:int* a=(int*)malloc(sizeof(int)*4);B和C:这都是在描述realloc的过程,这是realloc的两种情况;D:错误,只是会删除标记,但并不会清除空间内容
2、如下程序输出的结果是什么( )
#include <stdio.h>
typedef struct List_t
{
struct List_t* next;
struct List_t* prev;
char data[0];
}list_t;
int main()
{
printf("%d",sizeof(list_t));
return 0;
}
我们可以明显看出,List_t是一个双向链表,其拥有一个next指针(后继指针),和一个prev指针(前驱指针),以及一个十分特殊的结构:“柔性数组成员”或“零长度数组”data[0]。它允许你在结构体的末尾有一个大小可变的数组。这种技术常用于创建可变大小的数据结构,如链表。
接下来分析,两个指针在32位系统上各占4个字节,并且在内存中刚好连续存储,共占8个字节,而data数组的大小为0,不会增加结构体的总大小,所以答案为8或者16(64位系统)
3、以下程序的输出结果是( )
#include<stdio.h>
void fut(int**s,int p[2][3])
{
**s=p[1][1];
}
int main()
{
int a[2][3]={1,3,5,7,9,11},*p;
p=(int*)malloc(sizeof(int));
fut(&p,a);
printf("%d",*p);
return 0;
}
首先分析fut函数,无返回值,传入一个指向指针的指针,和一个二行三列的二维数组,并在函数体中解引用s让其指向的值等于p[1][1]
而在主函数中,有一个a[2][3]数组,存储了1 3 5 7 9 11这6个元素,并新建一个指针p,给p创建了4个字节的空间;这个时候使用fut函数,让p的地址指向a[1][1],也就是9,所以*p=9
4、以下有关C语言的说法中,错误的是( )
A: 内存泄露一般是指程序申请了一块内存,使用完后,没有及时将这块内存释放,从而导致程序占用大量内存,但又不使用不释放
B: 可以通过malloc(size_t)函数调用申请超过该机器物理内存大小的内存块
C: 无法通过内存释放函数free(void * )直接将某块已经使用完的内存直接还给操作系统,free函数只是将动态申请内存的使用权释放
D: 可以通过内存分配函数malloc(size_t)直接申请物理内存
A选项正确;B错误,如果使用malloc函数调用申请超过该机器物理内存大小的内存块,就会申请失败;C:正确,只是交还使用权,但是并未清除使用过的内存里面的内容;D:正确
5、若要用 fopen 函数打开一个新的二进制文件,该文件既能读也能写,则文件方字符串应是( )
A: “ab++” B: “wb+” C: “rb+” D: “ab”
对于要打开一个新的二进制文件,并且该文件既能读也能写,应该使用模式字符串 “wb+”。这里的模式字符串的含义如下:
“w” 表示写入模式。如果文件不存在,则创建一个新文件;如果文件已存在,则清空该文件。
“b” 表示二进制模式。在二进制模式下,文件会以原始的字节形式进行读写,不会进行任何特定的转换。
“+” 表示更新模式。这允许文件既能读取也能写入。
因此,正确的答案是 B: “wb+”。
二、编程题
//解题版本
int multiply(int A, int B){
if(A>0&&B>0)
return A+multiply(A,B-1);
return B;
}
//高级版本(可以算负数的乘法)
int multiply(int A, int B){
if (B == 0)
return 0;
if (B > 0)
return A + multiply(A, B - 1);
else
return -(A - multiply(A, -B + 1));
}
其实这里也很巧妙,首先我们的判断条件是A和B都大于0,并返回A+multiply(A,B-1),最后当B=0时,刚好A与自己的相加次数刚好就是B的值,最后返回B的值,也就是0。
#include <stdio.h>
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int i,m,b;
int cnt=0;
for(i=1;i<=n;i++)
{
m=i;
while(m)
{
b=m%10;
m=m/10;
if(b==7||m==7||i%7==0){
cnt++;
break;
}
}
}
printf("%d\n",cnt);
}
}
输入n的值之后,创建了三个变量i,m,b以及cnt(count),i是用来遍历1~n之间的数,而m是用来当i的替代品,用来计算,b是算m%10的约数,看其当前最后一位上是否为7,而后面的m/=10则是为了删除掉最后一位数;如果b==7(刚才的最后一位数为7),或者m= =7(此时的最后一位数为7),抑或是i%7= =0(i是7的倍数),都会证明这是符合题目条件的数,cnt++并跳出此次循环