
C语言
文章平均质量分 84
金创想
这个作者很懒,什么都没留下…
展开
-
“半身不遂”的逗号操作符
逗号(,),意味着两边是不完整的,它不光能分隔变量、参数,还能作为操作符参与运算。今天就来讲讲逗号操作符。原创 2025-01-25 19:26:02 · 847 阅读 · 0 评论 -
弄懂了这一循环,你才真正明白啥是“生米煮成熟饭”
③不是以单项为单位总结每一项式子的规律,建立起每项的值与第n项的关系,而是以两项为一组,符号一正一负,前后项分母差2。因为最后一项可能是这一组中的前一项,也可能是后一项,需要在每一项后都加入判断,这个判断非常容易遗漏。do就是做嘛,while就是判断嘛,组合起来就是先做后判断,也就是不管三七二十一,先干了再说,用一句生活术语来说,就是先把生米煮成熟饭。所以必须要先运算后判断,而我家娃娃的代码恰恰忽略了这点,掉入本题最大的陷阱。的含义,就像前面说的,它的意思很明确,计算的式子的最后一项要小于。原创 2025-01-24 20:20:02 · 1019 阅读 · 0 评论 -
逻辑运算符的优先级老是忘?只因你没想明白它的逻辑!
大多部编程语言中,逻辑运算符的优先级都会设置成!> &&>||,你有没有想过,这是为什么呢?原创 2025-01-21 18:56:38 · 930 阅读 · 0 评论 -
1秒写出逻辑运算符的优先级判定表达式
如果你懒得动脑,且又一把子力气无处安放,可以试试把所有情况全部输出出来,让电脑帮咱找出那些输出结果不同的。通过将括号放到不同的位置,改变运算的优先级,然后看第1个表达式的输出结果与后面哪个表达式相同,即可简单判断出他们的优先级。这个力气咱不白花,细心观察,你会发现一个规律:头尾两个数,与&&挨着的必须是0,与||挨着的必须是1。这段代码考验脑筋的地方在于,要巧秒配置1和0,使括号放在表达式前面、后面的输出结果是不一样的。知道了这个规律,下次你忘了他们三个的优先级,就可以立刻无脑写出用于验证的表达式。原创 2025-01-17 16:55:40 · 1209 阅读 · 0 评论 -
整数的分离与合成
整数是由数字和数位组成的,比如327是一个三位数,它的数字是3、2、7,数位是个数、十位、百位。经常有些题目考查将一个整数拆分成各个数字,以及将各个数字合成一个整数,下面分别就此讨论。注:只考虑正整数,只涉及整数拆成单个数字,单个数字合成整数的情况,不考虑整数拆成多个整数,多个整数合成一个整数的情况。原创 2025-01-16 20:00:00 · 694 阅读 · 0 评论 -
优先级和结合性:搞定C语言的“多边关系”
你知道下面的表达式在C语言里意味着什么吗?下面就这个问题说道说道。原创 2025-01-15 20:00:43 · 1012 阅读 · 0 评论 -
一次为多个变量赋值的方法
从形式上a=b=c=1是符合这个定义的,但却忽略了一个问题:C语言中的等号是“赋值运算符”,表示将右侧的值赋给左侧的变量,而并不表示等号左右两边相等,它与数学中的等号意义是完全不同的。这其实很好理解,因为赋值就将等号右侧的值赋给左边的变量,就像从右向左传球一样,所以如果有一堆串联的等号,值的源头一定是在最右边,故而也自然从最右边算起。所以,作为编程人员,知道怎么求解此类题目即可,在编写代码时不推荐用这种赋值方式。有的书上称之为“串联赋值”,意思是把多个等号串联起来赋值,这种叫法更合理些。原创 2025-01-14 20:31:11 · 784 阅读 · 0 评论 -
初学者常犯:编程等号与数学等号划等号
因为在C语言中,赋值运算符是把值赋给变量,等号左边的一定要是变量,2=a不符合语法,编译器遇到这种代码时就会报错,从而起到帮助程序员纠错的作用。初学者在if、while、for等语句中表示逻辑判断时,经常将双等号(==)误用为等号(=),导致运行结果出错(注意是运行结果出错,编译时程序是可以正常通过的,所以这种错误不易发现)。在C语言中,等号(=)表示赋值操作,即将右侧的值存放到左侧的变量中。a=a+1这个式子在数学中显然是不成立的,但在C语言中却是成立的,它表示将变量a的值加1,再赋给变量a。原创 2025-01-13 17:00:00 · 1934 阅读 · 0 评论 -
数学函数的参数和返回值探秘
按要求参数不能是整数,返回值也不能是整数。所以按理sqrt(9)是不符合函数要求的,而应写成sqrt(9.0),但实际上,用sqrt(9)也能输出正确结果。这一点其实也很好理解,函数的原型就是sqrt(arg),它的参数归根到底只有arg,至于arg是怎么计算来的,取决于它本身的表达式,和函数本身没有关系(即19/2的值只与19/2这个表达式本身有关,和sqrt函数无关)。注意sqrt((double)(arg))参数中的这两个括号都是非常有必要的,感兴趣的可以用下面的代码测试一下,就可以看出其中的玄机。原创 2025-01-12 19:53:50 · 1060 阅读 · 0 评论 -
C语言结构体简介:“结”在一起,“构”成一“体”
我们一般把结构体中的元素称为“成员”,这些成员的定义就和定义普通变量的方法一样。结构体就是拉了一伙“成员”,组成个大家庭,这个大家庭的名字由大括号前的结构体名定义。注意,这种用大括号{}的初始化方式只能在定义变量的同时进行,就和数组的初始化是一样的。因为已经定义了结构体变量,hero与它上面的结构体自然地捆绑在一起,所以这种情况还可以把结构体类型的名字Person省略掉。它传递的是全部成员的值,也就是将实参中成员的值一一赋值给对应的形参成员。结构体中的元素类型不能是结构体本身的类型。原创 2024-12-29 20:27:18 · 726 阅读 · 0 评论 -
“位”你着迷:趣味位运算合集
因为每执行一次n & (n - 1) 可以消除最后一个 1,所以不停地进行n & (n - 1),直到结果变成 0,就可以求出一共消除了多个少1。要判断一个数是奇数还是偶数,一般首先想到的都是对2取余,但其实有更高明的算法。只需要用到一个简的位运算:用这个数“& 1”,结果为0即为偶数,否则为奇数。按位异或^可以代替“三变量法”,在不增加临时变量的情况下实现两个数的交换。利用n&(n-1)可以将n的二进制形式的最后一个1去掉。所以如果n & (n - 1)的值为0,则n就是2的幂。原创 2024-12-25 20:00:00 · 1688 阅读 · 0 评论 -
释放本我的“绝对值”
这很好理解,起初,神创造天地,在没找到夏娃之前,老金两手空空、只顾一个猛子扎水里抓鱼吃,后来,老金技术练到家,抓到的鱼吃不完,就有了存货,于是自然在脑子里就产生了“有和无”的概念。那就把范围扩大,于是老Y开始刨路,把好好的路刨开,再重新铺好,花费了更大的力气,产生了更大的GDP。在数轴上,它体现的是与代表“无”的基准点0之间的距离“有多少”;在我们的人生中,它体现的是我们的财产“有多少”,花费的力气“有多少”;走的路程不能为负,花费的力气不能为负,产生的GDP不能为负,这些不能为负的东东,就是绝对值。原创 2024-12-03 20:06:55 · 557 阅读 · 0 评论 -
野指针:编程界的“野孩子”
因此,如果函数返回了一个指向局部变量的指针,那么这个指针将指向一个已经不再有效的内存区域,即所谓的“悬空指针”。当然,在使用动态分配的内存时,还需要注意在适当的时候释放它,以避免内存泄漏。此时,指针变量的值是随机的,它可能指向任何一个内存地址,而这个地址很可能是程序不应该访问的。你可能因此而闯入一个充满毒蛇猛兽的火山口上面,没人理会你的哭叫,没人理会你的哀嚎,被别人狠狠地,毫不怜悯地将你用脚一踢,踢到滚烫的岩浆里头。这是野指针的进阶版,内存释放后之后,指针就如幽灵一样,已经死了,却还有那么一缕灵魂。原创 2024-11-27 20:00:00 · 1174 阅读 · 0 评论 -
全局变量与静态变量的区别
因为它的值一直存在内存中,所以如果把静态局部变量放在函数中,即使在函数返回后,再次调用该函数时,该变量仍会保持上次调用结束时的值。静态变量可以是全局作用域内的静态变量(在main函数外声明的静态变量),也可以是局部作用域内的静态变量(在main函数内声明的静态变量)。作用域、链接性指的是变量可以在什么地方使用,生命周期指的是变量的值在内存中保留多久,前者是空间属性,后者是时间属性。无链接性,因为只在声明它们的函数或代码块内可见,所以它们是属于花括号的私人所有,金屋藏娇,别人连勾搭一下都不行。原创 2024-11-15 17:03:57 · 1849 阅读 · 0 评论 -
内存泄漏简介:不断消耗资源的吞噬者
你一直占着茅坑一直拉,你占的时间越长别人能用的时间就越少,你拉得越多别人能拉的就越少。内存心里苦啊,就好像古代宫中的三千佳丽,很多连皇上的面都没见过,却又不能交别的朋友,白白地虚耗了青春。这是很简单的道理,就像你占着茅坑,只顾一直拉啊拉,从不去淘宝,最后就会溢出来。遵循编程语言和开发框架的最佳实践,例如使用RAII思想管理资源,用适当的数据结构、算法和编程范式等,可以减少内存泄漏的发生。全局和静态变量的生命周期与程序一致,如果它们持有动态分配的内存,那么这些内存将在程序结束之前一直无法被释放。原创 2024-11-13 16:48:48 · 612 阅读 · 0 评论 -
“&“和“*“:身怀绝技的双飞客
也有超级侦探的一面,这位神探善长的技能是按图索骥,只要你给出任何人的地址,它就能立马找到这个人。C语言里指找到用于获取指针指向的变量的值,其实也就是这个变量本身(值就是变量到底是什么,是变量的本质)。自然不是int型,也不是double、char型,她绝不是这么普通单调乏味的类型,一定是一个综合类型,就叫她“对象”吧!对两个操作数的每一位进行逐位比较,相应位都为1时,结果的相应位才为1,否则为0。"&"和"*"是C语言里面的两个斜杠青年,不同的形式具有不同的作用。星号还用于声明一个指针类型的变量。原创 2024-11-12 14:26:19 · 392 阅读 · 0 评论 -
指针简介:欲送你花,先找你家
在声明指针时,*被称为“指针声明修饰符”,虽然叫了个新名,但和前面讲的解引用运算符本质上是一样的,都是获取指针指向的变量的值。的本质含义是这样的:取出指针p指向的变量的值,这个值是int类型的。的意思是p是一个指针,*p是int类型。说的是取出指针p指向的变量(为方便说明,假设这个被取出来的变便为q)的值,这个值还是一个地址,然后再取出q指向的变量的值,这个最后取出来的值是int型,也就是**p是int型。指针偏移指的是加减运算,需要注意的是,加减的单位不是字节,而是指针所指向的数据类型的大小。原创 2024-11-08 18:57:47 · 1613 阅读 · 0 评论 -
强制结束输入的方法
如果输入:2 CTRL+Z,结果和前面一样,也能实现强制结束输入的效果,有人就会误认为这里是CTRL+Z起到了发出“输入结束”信号的作用。从表中可以看出,输入“2 x”和“2 CTRL+Z”无论是求和结果还是scanf函数的返回值都是一样的,因此二者是一回事,都是靠输入类型不匹配实现强制结束输入。一文中讲过, Windows的输入结束信号是Ctrl+Z,具体步骤是:输入完毕后按Ctrl+Z键,再按Enter键,即可结束输入。如果scanf要求输入两个数,现在只输入一个数,想要结束输入该怎么办呢?原创 2024-09-02 11:52:50 · 888 阅读 · 0 评论 -
合成数的高效算法
它本质上是从最高位开始计算的,每增加一位数,就用原数乘以10加上新增加的数,就能得到合成后的数。“位值法”(Positional Value Algorithm)中的位就是位置,值就是数值,即数字在其所在位置上的值,比如9在千位这个位置的位值是9000。这暗示此记数法的最大特点在于把数的“位置“作为衡量数大小的参数,即每个数字在不同的位置代表的权重是不一样的。用公式来表示:数=∑数字*位置权重。在这种记数法中,一个数的大小用一组有顺序的数字来表示,数的大小既取决于数字的值,也取决于数字的位置。原创 2024-08-15 16:50:12 · 1864 阅读 · 0 评论 -
预处理指令简介
也就是说,预处理是编译的“前戏”,不是正式程序的一部分。自驾游时,我们眼脑四肢并用,打火,挂档,给油,看路,瞟导航,这些操作就像我们在敲代码。#error指示编译器在编译时生成一个给定的错误信息,常将它嵌入到条件编译结构中,这样可以基于编译时的条件来决定是否触发这个错误。预处理器会检查#if或#elif后面的常量表达式,如果为真(非零),则编译对应的代码段。(4)#pragma:用于向编译器发出指令,有哪些指令由编译器厂商自行定义,因此不同的编译器可能支持不同的 #pragma 指令。原创 2024-08-14 17:00:06 · 552 阅读 · 0 评论 -
assert宏的源代码解析
这句代码的意思是说,如果NDEBUG被定义了,assert宏将被替换为一个什么也不做的表达式((void)0)。0是个整数,表示没有数量,但它毕竟还是个数,还能给变量赋值,但一旦转换为void型,这个功能也丧失了,所以(void)0相当于什么也不干。这部分代码中的 ,0 是为了确保整个宏的扩展始终是一个表达式,其值在_Expression为真时为_Expression的值(由于 || 短路),而在 _Expression为假时为 0(因为逗号表达式的值是最后一个表达式的值)。b) \ 是宏定义中的续行符。原创 2024-08-13 16:42:06 · 1059 阅读 · 0 评论 -
const定义常量详解
这意味着你不能改变指针本身的值(即它指向的地址),但你可以通过这个指针来修改它所指向的数据(如果数据本身不是常量的话)。好比你练得一手六脉神剑,手指可以乱指一通,但你即便把它指向故宫,也无法将之推毁,因为这是个保护性建筑,不能被改变。聪明如你可能会问:既然是常数,我直接在代码中用这个常数本尊不就完了,比如直接用π的值3.1415926,干嘛要费事地把它定义为一个常量呢?聪明如你可能又会问:那我只要定义为变量就可以了,我知道这是个常数,自然不会闲得蛋疼去改变它,有什么必要加个const呢?原创 2024-08-08 16:53:51 · 1130 阅读 · 0 评论 -
标识符的分类
(5)预定义宏(也称内置宏):预定义宏是编译器预先定义好的宏,具备特定的功能,不需要用户使用#define定义就可以直接使用。(4)系统常量名:预先定义在头文件中的宏常量,通常为数学常量、物理常量或其他与特定库或框架相关的常量,如NULL(空指针)、M_PI(π)。预定义标识符和关键字的区别在于,用户可以重新定义预定义标识符另作他用,但这将失去预先定义的原意,所以不应随便更改这类标识符。标识符(identifier)是标识某个实体的符号,是程序员给变量、常量、函数、语句块等起的名字。原创 2024-05-24 17:35:41 · 1896 阅读 · 0 评论 -
C语言布尔类型的前世今生
正常布尔类型只占1个字节(这其实也是bool类型的一个存在价值,占用内存比int型小),但因为bool被替换为int,所以sizeof(bool)输出的是4个字节。因为#define bool int的存在,在编译时会自动将所有的bool替换为int,相当于这个新设的bool类型完全没起作用。只是这个布尔类型不是像bool、BOOL这样的美男子,而是这样一个怪胎:_Bool。从此以后,我们不用自己造炮了,只要加上头文件,就可以像其他语言一样使用bool、true、false。原创 2024-05-21 16:44:36 · 746 阅读 · 0 评论 -
一文搞定“宏”
它用于宏定义中的替换列表中,会把其后的宏参数转换为一个用双引号(quotes)括起来的字符串。宏替换就是简单的文本替换,它是在编译阶段完成的(相当于Word里的查找替换),因此它在执行时不需要函数调用的开销:传递参数和返回值等,所以宏比函数在程序的内存开销和速度方面更胜一筹。需要注意的是,如果类函数宏的参数含有逗号,逗号只会被识别为参数的分隔符(separator),而不会被识别为逗号操作符。①条件判断(x++)>( y++),结果:x++表达式的值为3,y++表达式的值为7,x=4,y=8。原创 2024-05-17 17:47:39 · 1829 阅读 · 0 评论