c程序语言设定定义域,高观点下的C语言入门

2023-10-20 20:10

本文主要是介绍c程序语言设定定义域,高观点下的C语言入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

C语言,是大多数科班出身的程序员的第一门语言,也是大多数底层技术爱好者的主要语言。

在计算机领域,底层技术就是核心技术。

C语言刚入门时,其实还是很别扭的,因为它的设计与高中数学教育形成的思维惯式不太一样。

1,相等==和赋值=的区分,

在数学里,一般不需要特别的符号来区分相等和赋值,人们可以根据上下文的语义知道表示的是什么。

x=1的同时也就暗含了x==1,在给人看时不需要特意说明这点。

但在电脑程序里需要区分,因为电脑的理解力比人差得多,也就需要在程序设计时添加更多的细节。

比较x是否等于1,和让x等于1,是两种不同的运算。

必须给电脑明确指出,它才能正确运行。

因此,我们需要两个“不同但又类似”的符号,作为这两个关联场景的运算符,C语言选择了=用于赋值,==用于相等。

不等,则使用了!=,因为ascii码里没有数学上那个不等号,如果使用ascii码之外的符号就会需要额外的输入法软件,这对编程语言是不可接受的。

没有哪个程序员在编程时想切换输入法,除非它要输入非英文字符串。

之所以不让==表示赋值,而让=继续符合人们中学时学的通常语义,是因为赋值比相等在程序里出现的次数更多。

比较运算可以是>、>=、 < 、<= 、!= 、!,==出现的次数其实不多。

但赋值,包含扩展的+=、-=之类的,出现的次数特别多,可以少打一个符号。

对使用频率高的词汇使用较短的编码,是所有语言的惯例。也是符合“信息论”的编码原则的。

“我”,在汉语里的笔画算比较少的,而且结构很醒目。

英语则是I,法语是Je,这种高频次的第一人称代词,一般都是简短+单音节+元音结尾的词。

第三人称的“是”,也是另一个高频词汇,英语是is,法语是est,例如多邻国的名句:C’est une fille anglaise.

汉语是典型分析语,语义表达不依赖动词形式变化,所有人称的“是”都一样,但这个字也笔画简单而结构显眼。

书法好的可以把它写地龙飞凤舞,大气磅礴。

回到C语言,另外,如果赋值使用了==,那么频次不低的+=就变成了+==,三个字符不但会给词法解析带来额外负担,还会让程序员多打一个字符:(

程序员都是懒人,否则他们就不会把重复的活儿给电脑做了:(

+=在循环语句里用于变量的自增,使用频率仅低于++。

2,从0开始计数,

这也是很不符合惯例的设计。

人们数数是从1开始,0在数学史上出现也是较晚的,比1晚的多。

但是在二维数组中,如果从1开始计数,那么2行16列的数组,16是第1行最后1个元素,17是第2行第1个元素。

可是,16/16=1余0,17/16=1余1,它们的数组索引与它们与数组大小的除法结果就不一致了:

“商+1”才是行号,但余数是0时商又不需要+1,这在编程时会额外消耗程序员的脑力,而且这种计算细节很容易出错。

另外,就是索引值与元素在数组中的实际偏移量不一致。

第1个元素与数组首地址的偏移量是0,而不是1,&a[1]对应的是a+1 - 1 = a+0。

就跟公元1世纪不是1xx年,而是xx年一样,算起来别扭又烧脑。

如果让索引号和偏移量一致,那么0号位的内存就浪费了。

这在内存稀缺的上世纪70年代,是不可接受的。

最后,为了让数组索引与除法/和模运算%的结果一致,就从0开始计数了。

模运算%的结果一致叫做“同余”,线性同余方程组的求解,最早可以追溯到中国古代数学著作“孙子算经”。

宋代大数学家秦九韶在“数学九章”中把这个解法叫做“大衍求一术”,现代的抽象代数里叫做“中国剩余定理”。

秦九韶的解法,同时也是这个定理的“构造性证明”。

构造性证明,比存在性和唯一性的证明要牛,因为它同时给出了求解步骤。

中国古代在代数学领域还是很牛的:(

几何学上可能古希腊牛一些,毕竟欧几里德比较牛,“几何原本”,“古希腊三大难题”。

但古希腊三大“几何”难题,最后都是靠“代数”否决的:(

3,变量,

变量的出现伴随着方程的诞生,可以追溯到一元一次方程的出现,久得估计没法考证了。

秦九韶解线性同余方程组的中国剩余定理,肯定比这个晚了至少上千年。

方程确定的是隐函数,函数确定的自然是显函数。

4,函数,

C语言的函数和数学上的函数有点区别,它是一个处理某个功能的代码模块,可以被另一个函数调用。

它也和数学上的函数一样有参数(自变量),也有返回值(结果),这可能是它也叫做函数的原因。

它也是从参数空间(定义域)到返回值空间(值域)的一一映射:在代码没有BUG的情况下同样的参数该算出同样的结果来。

调用时需要传参数,参数和返回值在不需要的时候也可以没有,void f()这种。

整个程序的入口函数就是main函数,它被操作系统加载程序时调用,Linux的这个API是execve()。

5,指针,

指针,是C语言的压轴章节。

这章之后,就是文件读写的API了,严格来说不属于编程语言范畴,而是属于IO库的范畴。

“去书架上把C primer plus借来”。

书架就是“指针”,是C primer plus这本书存放的位置。

C primer plus就是指针的内容,即书架上存的是什么。

内存就是计算机的“书架”,内存里的值就是这个“书架”上的“书”。

对于电脑来说要尽量细化,所以给内存按字节编号,指针就是这类编号。

还可以给书里的章节编号,那么书架就是二级指针,书是一级指针,章节是指针的内容。

地址,在日常生活中也是常见的。

寄快递需要有地址和收货人,去某地址找某个收货人,把快件交给他之后,他的总体重量增加了1公斤,就是*p += 1。

6,递归,

递归,就是利用“函数栈”保存上下文状态的迭代。

递归比迭代难理解,但在编程上比迭代容易实现,因为它不需要手动保存上下文状态。

按照数学归纳法,当k = 0的时候条件成立,当k = n的时候也成立,当k=n+1的时候也成立,计算k = 10的结果。

从k=0开始,根据迭代公式,一直迭代到k=10,每一步都要保存k跌代到哪里了,结果是什么。

k和结果就是上下文,手动管理它们的存放就是迭代,把它们写在函数参数里,让程序在函数调用的过程里自动管理,就是递归。

参数,也是函数的局部变量,局部变量的管理由编译器实现,实际上简化了程序员的工作难度。

二叉树遍历时,开一个动态数组,不断把遍历到的节点按遍历顺序存进去,同时记录哪个分支遍历过了,哪个分支没有遍历,迭代到哪里了,实际是比较麻烦的。

但是,用函数栈来存储状态,就只需要改变每次迭代的参数就可以了,代码就简单得多。

递归难理解,可能在于它是反向迭代,大多数场景下的都是从10跌代到0,截至条件与日常经验是反过来的。

倒着数数,相对比较别扭。

7,字符和字节,

单字节并不足以表示全球主要语言的所有常用字符,char作为1个字节的变量同时表示字符,是ascii码时代的遗迹。

那个时候字符和字节的语义是一致的。

unicode的出现比较晚,所以C后来又添加了wchar类型,但char已经在各种代码里用惯了。

char既当字符变量,又当单字节变量,char*还作为缓冲区的指针,又当作字符串,差别只在于结尾0。

然后就有了著名的缓冲区溢出漏洞:(

不在字符串的string类型中记录长度,而是靠结尾的哨兵0,最后不得不搞出了各种snprintf函数。

每次strcpy、sprintf时都要在心里默算缓冲区够不够。

优点就是vsnprintf()函数的实现比较简单,因为字符和整数可以直接运算,

x % 10 + ‘0’就是数字要打印的字符。

char和char*字符串的使用,在C里是特别容易出BUG的地方。

本来,字符应该是无符号的,但是在char同时充当了有符号的单字节整数的情况下,就导致了char型的0x80在编译器扩展时成了负数。

unsigned char型的0x80是正的。

char在与int计算时需要注意它的最高位是0还是1,因为编译器会做符号扩展。

b23926a30f657f6b503a1dddc6dbf4fb.png

举报/反馈

这篇关于c程序语言设定定义域,高观点下的C语言入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/249456

相关文章

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

C语言实现两个变量值交换的三种方式

《C语言实现两个变量值交换的三种方式》两个变量值的交换是编程中最常见的问题之一,以下将介绍三种变量的交换方式,其中第一种方式是最常用也是最实用的,后两种方式一般只在特殊限制下使用,需要的朋友可以参考下... 目录1.使用临时变量(推荐)2.相加和相减的方式(值较大时可能丢失数据)3.按位异或运算1.使用临时

使用C语言实现交换整数的奇数位和偶数位

《使用C语言实现交换整数的奇数位和偶数位》在C语言中,要交换一个整数的二进制位中的奇数位和偶数位,重点需要理解位操作,当我们谈论二进制位的奇数位和偶数位时,我们是指从右到左数的位置,本文给大家介绍了使... 目录一、问题描述二、解决思路三、函数实现四、宏实现五、总结一、问题描述使用C语言代码实现:将一个整