第七十一天学习记录:对陈正冲编著《C 语言深度解剖》中关于1、2、4,5章作者留下部分问题的学习

这篇具有很好参考价值的文章主要介绍了第七十一天学习记录:对陈正冲编著《C 语言深度解剖》中关于1、2、4,5章作者留下部分问题的学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问:有如下代码。

static int j;

void fun1(void)
{
	static int i = 0;
	i++;
}

void fun2(void)
{
	j = 0;
j++;
}

int main()
{
	int k = 0;
	for (k = 0; k<10; k++)
	{
		fun1();
		fun2();
	}
	return 0;
}

i 和 j 的值分别是什么,为什么?
答:
在这份代码中,变量 i 和 j 分别是函数 fun1 和 fun2 的静态局部变量。静态局部变量在函数内部声明,但在整个程序生命周期内都存在,且只初始化一次(第一次进入函数时初始化)。

在 main 函数中,fun1 和 fun2 分别被调用了 10 次,这意味着变量 i 和变量 j 都被分别累加了 10 次。但是由于变量 i 是函数 fun1 的静态局部变量,所以它的值在每次 fun1 调用后都会被保留。因此,最终 i 的值是 10,而 j 是一个全局变量,每次 fun2 调用都会将其值重置为 0,所以最终 j 的值是 1。

问:在 switch case 语句中能否使用 continue 关键字?为什么?
答:
在C/C++中,可以使用continue关键字来终止当前循环中的迭代,并开始下一轮迭代。但是,在switch-case语句中,不能使用continue关键字。

原因是,在switch-case语句中,switch关键字后跟随一个表达式,这个表达式决定了程序流程的走向。case标签则是用来匹配表达式结果的值之一。当匹配成功时,程序会执行对应的分支,并直接跳转到switch语句的结束位置,而不是进入一个循环体内部。因此,在switch语句内部使用continue关键字是没有意义的,也是无效的。如果需要提前结束switch-case语句的执行,可以使用break关键字来实现。

需要注意的是,在含有循环语句的switch-case代码块中,仍可以使用continue来终止当前循环中的迭代,并开始下一次迭代。但是,这与switch-case语句本身并没有直接联系,而只是循环语句的一种使用方式。

问:return ;
这个语句有问题吗?如果没有问题,那返回的是什么?

答:
return ;语句在函数中表示空返回,即返回值为空,并且结束当前函数的执行。这个语句不会报错,是合法的语法。

当函数的返回类型为void时,可以使用return ;来显式地返回空值。如果没有写return语句或者return后面没有指定返回值,也默认会返回一个空值,即函数的返回值为void。

当函数的返回类型不是void时,直接使用return ;是不合法的,编译器会报错。此时必须提供与返回类型相符的返回值表达式,将其作为return语句的参数来进行返回。

问:case 语句后面是否可以是 const 修饰的只读变量呢?
答:
在C/C++的case语句中,case标签后可以是常量表达式,但不能是变量。常量表达式是指在编译时就可以计算出结果的表达式,可以由字面值、枚举常量、const 变量或者 constexpr 函数等构成。

常量变量是指定义时使用了关键字const修饰的变量,它们的值在定义后不可更改。但是,在case标签后不能使用常量变量作为标签值,因为常量变量只有在运行时才能获取其值,而case标签要求在编译时就可以确定其值。

如果需要在switch-case语句中使用变量作为标签值,可以使用default标签来代替,然后在switch语句内部使用if-else判断来实现相应的逻辑。
问:以下代码杂x86系统下输出为多少?

#include <stdio.h>
int main()
{
	int a[5] = { 1,2,3,4,5 };
	int *ptr1 = (int *)(&a + 1);
	int *ptr2 = (int *)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);
	return 0;
}

答:5,20

问:sizeof(ColorVal)的值为多少?为什么?
答:
sizeof(ColorVal)的值为4,因为枚举类型在内存中占用的空间是与int类型相同的。在C/C++中,枚举类型本质上是int类型的一种特殊取值方式,它只是通过标识符来方便地指代一组整数值,并不会改变其实际的数据类型。

因此,在定义枚举变量时,编译器会将其所定义的枚举类型映射为一个整数(如在上述代码中,GREEN=1, RED=2, BLUE=3,等等),并在内存中按照int类型的存储方式分配所需的空间。在32位机器上,int类型占用4个字节的空间,因此枚举变量ColorVal所占据的空间也是4个字节。

问:看看下面的代码:

#include <stdio.h>

int main()
{
	char a[5] = { 'A','B','C','D' };
	char(*p3)[5] = &a;
	char(*p4)[5] = a;
	printf("p3=%p,p4=%p,p3+1=%p,p4+1=%p\n", p3, p4, p3 + 1, p4 + 1);
	return 0;
}

上面对 p3 和 p4 的使用,哪个正确呢?p3+1 的值会是什么?p4+1 的值又会是什么?
答:
第七十一天学习记录:对陈正冲编著《C 语言深度解剖》中关于1、2、4,5章作者留下部分问题的学习
问:对 NULL 指针连续 free 多次会出错吗?为什么?如果让你来设计 free
函数,你会怎么处理这个问题?

答:
对 NULL 指针进行 free 是没有意义的,因为 free 会释放指向的动态分配内存,并将指针所指向的位置标记为未被分配状态。因此在调用 free 前需要对指针进行非空判断。

如果对一个已经被释放的指针再次进行 free ,就会发生 undefined behavior(未定义行为),包括程序崩溃,内存泄漏,程序运行出现不可预测的错误等情况,这是因为 free 函数只能释放一次动态分配的内存,多次释放同一块内存会破坏内存管理系统的数据结构。

为了避免这种问题的发生,我们可以在每次 free 后将指针赋值为 NULL,即:

int *p = (int *)malloc(sizeof(int));
if (p != NULL) { 
    // do something 
    free(p); 
    p = NULL;   // 将指针赋 NULL
}

这样即使误操作多次 free,也不会造成实际上的内存重复释放。

另外,还可以采用一些静态分析工具或者内存检测工具提前捕获类似的问题,避免出现重复释放内存的情况。文章来源地址https://www.toymoban.com/news/detail-480085.html

到了这里,关于第七十一天学习记录:对陈正冲编著《C 语言深度解剖》中关于1、2、4,5章作者留下部分问题的学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 学习Android的第十一天

    目录 Android ProgressBar 进度条 ProgressBar ProgressBar 外观 ProgressBar 属性 ProgressBar 方法 Android ProgressBar 动图替代圆形进度条 范例 Android ProgressBar 自定义圆环进度条 例子: 参考文档 在Android中,ProgressBar(进度条)是用于显示任务进度的UI组件,通常用于耗时操作的过程中以及需要显

    2024年02月19日
    浏览(30)
  • 15天学习MySQL计划-MySQL工具(进阶篇)-第十一天

    1.mysql 该mysql 不是指MySQL服务,而是指MySQL的客户端工具。 -e选项可以在MySQL客户端执行SQL语句,而不用连接到MySQL数据库再执行,对于一些批处理脚本,这种方式尤其方便。 2.mysqladmin mysqladmin是一个执行管理操作的客户端程序。可以用它来检查服务器的配置和当前状态,创建并

    2024年02月01日
    浏览(45)
  • 【80天学习完《深入理解计算机系统》】第十一天 3.5 过程(函数调用)

    专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录) 文章字体风格: 红色文字表示:重难点★✔ 蓝色文字表示:思路以及想法★✔ 如果大家觉得有帮助的话,感谢大家帮

    2024年02月11日
    浏览(30)
  • 【80天学习完《深入理解计算机系统》】第十一天 3.4 跳转指令

    专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录) 文章字体风格: 红色文字表示:重难点★✔ 蓝色文字表示:思路以及想法★✔ 如果大家觉得有帮助的话,感谢大家帮

    2024年02月11日
    浏览(29)
  • 第五十一天打卡

    中等 1.5K company 微软 Microsoft 给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 注意

    2023年04月09日
    浏览(25)
  • C语言(第三十一天)

    6. 调试举例1 求1!+2!+3!+4!+...10!的和,请看下面的代码: 调试找一下问题。 7. 调试举例2 在VS2019、X86、Debug 的环境下,编译器不做任何优化的话,下面代码执行的结果是啥? 程序运行,死循环了,调试看看为什么? 调试可以上面程序的内存布局如下:  1. 栈区内存的使用习惯

    2024年02月11日
    浏览(29)
  • 代码随想录第二十一天

    题目链接 : 二叉搜索树的最小绝对差 自己的思路 :和验证二叉搜索树一样的思路!可以求每个相邻节点的差值的绝对值,然后和之前的差值的绝对值进行比较,取最小的为新的res;递归三部曲:1、传入参数:当前节点;2、终止条件:如果当前节点为空,直接返回;3、单层递

    2024年02月16日
    浏览(38)
  • node 第二十一天 webpack 初见

    为什么需要学习(了解)webpack webpack是前端工程化的基石,webpack又是基于node进行文件打包bundle,所以作为前端起手学习node服务端开发,同时学习webpack是很有必要的。 随着vite的出现,vue这一脉可能也许不再需要学习webpack了,但是需要知道的是, 打包一定是前端工程化绕不

    2024年01月16日
    浏览(31)
  • 学C的第三十一天【通讯录的实现】

    ========================================================================= 相关代码gitee自取 :C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 学C的第三十天【自定义类型:结构体、枚举、联合】_高高的胖子的博客-CSDN博客  ==============

    2024年02月15日
    浏览(37)
  • 谷粒商城第十一天-完善商品分组(主要添上关联属性)

    目录 一、总述 二、前端部分 2.1 改良前端获取分组列表接口及其调用 2.2 添加关联的一整套逻辑 三、后端部分 四、总结 前端部分和之前的商品品牌添加分类差不多。 也是修改一下前端的分页获取列表的接口,还有就是加上关联的那一套逻辑,包括基本构件的引入、数据域的

    2024年02月13日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包