寒假作业Day 05

寒假作业Day 05

一、选择题

在这里插入图片描述

首先创建了一个二维字符数组,两行四列,并且第一行复制一个you过去,第二行复制me过去,第一行的最后一个字符复制&,所以打印arr的结果是you&me

2、如下C程序,在64位处理器上运行后 sz 的值是什么( )

struct st
{
	int *p;
	int i;
	char a;
};
	int sz = sizeof(struct st);

这个跟结构体的内存对齐有关,首先我们看处理器是64位的,也就证明指针的大小是8个字节,而默认对齐数是8,故对齐数还是8,而int则是4,char则是1,而结构体总大小需要为最大对齐数的整数倍,即8,16,24等等
在这里插入图片描述
所以第一个指针占8个字节,从0~ 7,而刚好下一个8是对齐数4的倍数,int类型占4个字节,所以从8~11,然后最后char类型占1个字节,12也是对齐数1的倍数,所以12填充;但是总大小12不是最大对齐数8的整数倍,所以要填充到16,故总大小为16

在这里插入图片描述

enum weekday是枚举型,虽然枚举类型从0开始,但是mon变量这里自己赋值了3,那后面的就要从3开始加,所以tue就是4,wed就是5,而后面workday被赋值wed,故答案为5

4、设有以下定义,则下面叙述中正确的是【多选】( )

union D
{
	int d1;
	float d2;
}d;

A: 变量d与各成员的地址相同
B: d.d1和d.d2具有相同的地址
C: 若给d.d2赋10后,d.d1中的值是10
D: 若给d.d1赋10后,d.d2中的值是10

联合的成员是共⽤同⼀块内存空间的,这样⼀个联合变量的⼤⼩,⾄少是最⼤成员的⼤⼩(因为联合⾄少得有能⼒保存最⼤的那个成员)。所以我们知道A选项对
B与A同理
C:这是不正确的。首先,你不能直接将一个浮点数10.0赋给d.d2然后期望在d.d1中看到整数10。浮点数和整数的内部表示是完全不同的。即使你以某种方式将浮点数10.0f的位模式解释为整数,你也不太可能得到值10。
D:这同样是不正确的。当你给d.d1赋值为10时,你不能期望从d.d2中读取到浮点数10.0。因为整数10和浮点数10.0在内存中的表示是完全不同的。

在这里插入图片描述

当C语言程序使用malloc申请了内存但没有使用free释放它时,这通常被称为“内存泄漏”。但在进程的生命周期内,即使存在内存泄漏,进程仍然可以正常运行(尽管它可能会消耗更多的内存)。

然而,当进程被kill后,关于内存泄漏的问题就变得无关紧要了,因为:

A: 内存泄露 - 这个描述并不完全准确。内存泄漏是指在程序运行过程中,动态分配的内存没有得到释放,从而导致系统内存逐渐被消耗。但当进程被kill后,操作系统会回收该进程所占用的所有资源,包括内存。因此,从操作系统的角度看,不存在“内存泄漏”的问题,因为已经分配给该进程的所有内存都已经被回收。
B: segmentation fault - 这通常是由于程序试图访问不允许访问的内存区域(如无效地址)时发生的错误。这与进程被kill无关。
C: core dump - 当程序崩溃时,操作系统可能会生成一个核心转储(core dump)文件,其中包含程序崩溃时的内存镜像。但这与进程被kill时的内存回收无关。

因此,答案是 D: 以上都不对。当进程被kill后,操作系统会回收该进程所占用的所有资源,包括通过malloc分配但未通过free释放的内存。所以,从操作系统的角度来看,不存在内存泄漏的问题。

二、编程题

在这里插入图片描述

char* compressString(char* S) {    
    // 获取输入字符串的长度  
    int size = strlen(S);    
  
    // 如果输入是空字符串,则直接返回空字符串的副本  
    if (size == 0) {    
        return strdup("");   
    }    
    
    // 分配内存来存储压缩后的字符串  
    // 这里分配了比实际可能需要的更多的空间(最坏情况是每个字符后都跟着两位数字和一个null终止符)  
    char* compressed = (char*)malloc(size * 2 + 1);    
  
    // 如果内存分配失败,返回NULL  
    if (!compressed) {    
        return NULL;   
    }    
    
    // 初始化压缩字符串的索引和当前字符的计数  
    int index = 0;   
    int count = 1;   
    
    // 遍历输入字符串(从第二个字符开始)  
    for (int i = 1; i < size; i++) {    
        // 如果当前字符与前一个字符相同,增加计数  
        if (S[i] == S[i - 1]) {    
            count++;   
        } else {    
            // 如果当前字符与前一个字符不同,将前一个字符和它的计数写入压缩字符串  
            compressed[index++] = S[i - 1];    
            // 使用sprintf将计数转换为字符串并追加到压缩字符串中  
            index += sprintf(compressed + index, "%d", count);   
            // 重置计数为1,因为新字符的计数从1开始  
            count = 1;   
        }    
    }    
    
    // 处理输入字符串的最后一个字符和它的计数  
    compressed[index++] = S[size - 1];    
    index += sprintf(compressed + index, "%d", count);   
    
    // 在压缩字符串的末尾添加null终止符  
    compressed[index] = '\0';   
    
    // 重新分配内存以精确匹配压缩字符串的实际大小  
    char* resizedCompressed = (char*)realloc(compressed, index + 1);    
  
    // 如果realloc失败,释放原始内存并返回NULL  
    if (!resizedCompressed) {    
        free(compressed);   
        return NULL;    
    }    
      
    // 如果压缩后的字符串长度小于原始字符串长度,则返回压缩后的字符串  
    // 注意:这里有一个逻辑错误,应该是比较strlen(resizedCompressed)和size,而不是size和strlen(resizedCompressed)  
    if(strlen(resizedCompressed) < size){  
        return resizedCompressed;    
    }  
    else{  
        return S;
    }  
}

*这个题目较难,所以需要大家去仔细理解,虽然逻辑简单,但实现较难

在这里插入图片描述

int exchangeBits(int num){
    int a = 0B10101010101010101010101010101010;
    int b = 0B01010101010101010101010101010101;
    a &= num; //保留奇数位
    b &= num; //保留偶数位
    a >>= 1;  //交换奇偶位
    b <<= 1;
    int ans = a | b;//分别将奇偶位组合在一起就可以
    return ans;
}
//定义一个整数a,其二进制表示是10101010101010101010101010101010。这个掩码用于选择num的奇数位(从右数起,第1、3、5...位)。
//定义一个整数b,其二进制表示是01010101010101010101010101010101。这个掩码用于选择num的偶数位(从右数起,第2、4、6...位)。
//对num和a进行与运算(&=)。由于a的偶数位都是0,所以这一步会保留num的奇数位,并将结果存回a。
//对num和b进行与运算。由于b的奇数位都是0,所以这一步会保留num的偶数位,并将结果存回b。
//将a右移一位。这会将原本的奇数位(现在存储在a中)移动到偶数位的位置。
//将b左移一位。这会将原本的偶数位(现在存储在b中)移动到奇数位的位置。
//对a和b进行或运算(|)。这一步会将重新定位的奇数位和偶数位组合起来,形成新的整数ans。

我们拿60来举一个例子,60的二进制是0B111100,所以a&=num的结果为0B101000,而b&=num的结果为0B010100,a>>=1的结果为0B010100,b<<=1的结果为0B101000,而a|b的结果则是0B111100,化为十进制则是60
*大家多看看,从中理解原理,这也是一道非常巧妙的题!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值