对于理工科新生,C语言这是一道不可逾越的障碍。在进入大学之前,许多人根本没有接触过与编程相关的内容,这导致这门课程的接受能力低,学习难度大。下面是一些内容的总结,这些内容在课堂上可能不会详细解释,但对于理解C语言更为重要,以供参考和讨论。
首先,让我们讨论一些基本内容。由于学校的教学时间有限,且每节课的时间相对较短,因此有必要在进入具体教学之前进行介绍链接,而且不会花费太多笔墨。大多数时候,我甚至告诉我的同学如何安装它IDE、如何创建一个新的文件,保存,编译和运行它,但它不会告诉学生为什么这样做,以及他们在每一步后面做了什么。为了解决这些问题,我们首先需要知道一些事情编程语言让我们从分类开始。
编程语言是如何分类的?事实上,编程语言有很多分类方法。首先,它们可以分为高级语言和低级语言高级语言有很多种,下面将介绍。
高级语言和低级语言首先,它可以根据高级和低级分为机器语言(汇编语言)和其他语言。高级语言有很多种类。让我们先谈谈低级语言。
机器语言仅由0和1组成。它是一种可以被计算机硬件直接理解的语言。不同的体系结构——如arm、x86、risc-v等——有不同的机器语言。机器语言可以直接操作处理器操作码计算机中有相应的电路。
汇编语言是在机器语言基础上诞生的语言。每条语句都对应于机器语言中的操作代码,可以直接翻译成机器语言。它存在的意义在于程序员很容易理解它。
上图:汇编语言和机器语言的比较
举个简单的例子:如果你想加两个数字,比如2+3,那么机器语言可能是000000110000001000000011(为了方便起见,这里添加了空格。在实际的机器语言中没有空格,只有0和1,机器代码由个人组成,只是用作示例,而不是某个架构实际使用的机器代码),虽然它是用汇编语言编写的ADD2,但这是一种更容易理解的方式。当然,汇编语言远不止这些,但由于本文不主要介绍汇编语言,因此不会深入讨论。
然而,汇编语言仍然非常复杂,并且有很多限制。一旦你需要编写一些复杂的函数或算法操作,很容易在编写后无法自己阅读。我在学习微机原理我写了一个课程项目。要求用89C51单片机编写一段摇计数代码,不包括驱动液晶屏的代码。总共只有四五百行,但有将近三百行的笔记是为了理解而写的。虽然我不擅长编译有一些原因,但可以看出它的复杂性。
因此,显然不可能用机器语言或汇编语言编写复杂的代码。这时,高级语言应运而生。下面简要介绍高级语言及其分类。
汇编和解释其次,通过语言翻译介绍了分类。以三种非常流行的语言为例,它们是C语言、Python和Java。
因为所有编写的代码最终都会变成机器语言来执行,不同的语言最终会达到相同的目的。只有通过不同的方式,不同类型的语言才能转换回汇编语言和机器语言。这里,我们首先介绍以C语言为代表的编译语言。
编译语言顾名思义就是通过编译将代码翻译成机器语言,然后执行。因此,代码将在执行之前先编译。当老师授课时,他会告诉学生,他们必须单击编译,然后单击执行,或者单击编译并执行。这就是为什么。编译器将调用现成的编译器来分析、优化和处理代码。由于空间原因,此过程在此不再重复。简而言之,在C代码被编译为Exe(在Windows下)或Out(在MacOS下)后,所写的内容将被总结可执行文件。
在编译C语言之前
C语言编译后
在这里,您可以控制编译器生成汇编语言文件。你可以看到两者之间的差距
上图:C语言和相应的汇编语言
显然,C版本更容易理解。
虽然编译后的语言会在执行前进行分析和优化,运行速度非常快,但对于大型程序来说,编译时间也会非常长。那么,您可以不编译就直接运行它吗?答案显然是肯定的。这是一种解释性语言,比如python。
对于解释语言,编译器将不用于翻译,最终生成机器语言的可执行文件以供执行。它将调用解释器,逐行翻译源文件,实时将每一行翻译成机器代码并执行。这样,就不需要编译,并且大大减少了执行前的准备时间。然而,由于解释器没有优化代码,每次都需要从头开始解释,因此执行效率不如编译语言。
编译语言还有另一个问题。如上所述,每个体系结构都有一种独特的机器语言,而编译过程就是将代码翻译成机器语言的过程,这导致每次编译生成的文件只能在特定的平台上运行。你能编译一次并在整个平台上运行吗?显然,这也是可能的。这是一种混合语言,比如Java。
这类语言也需要编译,但编译后生成的不是机器代码,而是字节码。通常,这种语言会被转换成机器代码,以便在运行时执行,或者由虚拟机直接解释和执行。因为它被编译成字节码而不是机器码,所以编译后的执行文件对于整个平台来说是通用的。
指定数据类型在学习C语言时,许多学生可能会想,数据类型的用途是什么?为了理解这个问题,让我们先看看数据是如何存储的。
数据类型的含义在内存中,所有数据都将二进制的用于存储,即01001和其他形式。这些数据只有0和1,表达的含义是人为指定的。
通常,第一位被视为符号位,即0位为正,1位为负。然而,如果我想让第二位代表符号位,它也完全符合规定,但所有涉及操作的代码都必须重写。数据类型用于指定每个位的含义。
例如,在32位系统中,对于int类型,第一位表示符号,最后31位表示特定值。为了float就类型而言,尽管第一位也代表一个符号,但其余31位的含义与int类型不同。接下来的8个数字是指数字,其余的是尾数,即科学计数表示法是尾数*(2^索引)。这里使用2的原因是计算机中的所有数据都是以二进制而不是十进制存储的。
上图:float式存储方法
这里,使用10000001000100000000000000000000000来显示float类型的具体计算。理解这一段需要一些简单的步骤二进制转换,如果没有,建议自己学习。通过二进制计算器,很容易得到它对应的十进制数是1094975488。
对于float类型,其指数为10000001,即129,然后根据规定减去127,得到其指数2。对于尾数,因为它必须以1开头,所以第一个1将被省略。因此,它的尾数实际上是1000000000000000000,即1.0001*(2^2),转换成4.25的十进制。
如果只想添加这两种类型的数据而不指定数据类型,程序集将直接添加位,即添加每个对应的0或1,并添加前一位的进位。这个计算将得到10000001000100000000000000000,这显然不是我们想要的1094975492.25。
如果未指定数据类型,计算将得到错误答案。可以看出,对于内存中无意义的二进制数字符串,我们可以通过指定每个位的含义来获得不同的结果。
许多学生可能也有这样的疑问,为什么它只是一个整数短的,Int、Lang、浮点数、Jet-Li、double和偶数字符类型对应于Int类型?int和double还不够吗?
由于现在计算机内存普遍充足,不太可能遇到内存空间不足的问题。因此,可以直接选择高精度数据类型进行存储和计算。然而,多年前,或者在嵌入式领域,在存储空间非常紧张的情况下,不同数据类型之间出现了差距。
在这种情况下,每一点都是宝贵的。因此,程序员将尽最大努力优化存储空间的使用。如果他们能使用低精度,他们就不会使用高精度。
和浮点数根据上面对存储模式的解释,精度越高,它所能代表的大小就越小。因此,当以高精度要求表示大数据时,有必要使用高精度数字。相反,它可以节省空间,但精度较低。由于float表达的准确度非常低,建议在学校里写C程序如无特殊要求,应采用双联式。
和烧焦类型是特殊的,可以用整数类型转换。在MCU和其他环境中,由于存储空间有限,我们更喜欢使用char,一种只消耗一个字节的数据类型,而不是更大的数据类型,如int。此外,char通常用于表示字符,因此如果您想表示,例如';A';这种类型的字符数据通常是char类型的。字符类型将在后面的字符串部分中提到。
然而,短类型不一定比int类型占用更少的空间,长类型也不一定比int表示具有更高的精度。这一切都取决于编译器(只有2<;=short<;=int<;=long是兼容的)。因此,如果你真的需要它,你可以使用char来减少消耗,而不是short。
上图:不同操作系统下数据类型的大小
可以看出,虽然常用的数据类型很少,但其他类型也有其存在的意义。它们不能被使用,但不能缺席。一旦确定了数据类型,就可以确定内存中分配的变量的大小和每个位的含义。
数组和指针了解数据类型,然后就可以定义数组了。数组是由一定数量的相同数据类型的变量组成的数据结构,也就是说,一个数组可以由一定数量的其他数组组成,这些数组也可以由数组组成,形成玩偶。
在C语言中,数组的长度和数据类型必须在定义时显式指定,而在其他一些语言中,如Java和python,数组的长度可以连续扩展,但在C语言中无法做到这一点。为什么?这需要从如何在内存中生成数组开始。
阵列生成当编译器创建一个大的数据数组时,它可以根据C语言所需的特定数据类型计算数组的长度。在这一步中,编译器可以计算它需要在数组中占用多少数据,一个数组是在一个连续的空间中生成的。但为什么是连续的空间而不是间歇性的?
访问阵列时,首先会找到其内存地址。创建数组时,数组的变量名实际上是指向数组第一项的指针(后面将讨论)。然后,根据特定的访问项,例如项n,该地址将添加n*sizeof(数据类型),并且可以直接找到该项的内存地址。因此,阵列在生成时需要应用连续内存地址,否则无法实现如此高效的访问速度。
C语言中的数组和其他语言中的数组所以问题来了:为什么其他语言可以扩展数组的长度,并通过变量初始化数组,而不是通过常量指定数组?
实际上,在最低的实现中,它们还将指定一个特定的值来生成数组,其原理与C语言完全相同。但是,当需要更长的阵列时,将应用更长的连续内存空间来存储新阵列,并且原始的旧阵列将在过去完全复制。当然,各种语言都会有一些优化,应用空间会略大于所需空间,以防止重复复制,降低运营效率。
上图:数组的动态扩展
由于C语言的数组是最原始的数组,因此该语言本身不会应用新地址、复制旧数组等操作,因此需要在初始化期间指定长度。
指针的作用另一个在开始学习时很难理解的概念是指针。让我们看看指针是什么。指针是一个存储内存地址的变量,也就是说,它可以直接访问和操作内存。
上图:指针图
在图中,a代表一个值为100的整数变量,它存储在内存中0x0010的地址中。因此,可以定义指向该地址的指针x。可以理解,地址0x0010存储在X中,访问该指针相当于访问该地址。这就引出了一个问题:既然指针存储地址并访问地址,为什么要定义类型?
原因很简单,因为需要取出地址的特定存储值。如前所述,数据类型决定了数据的大小以及每个位所代表的内容。因此,要获取存储在地址中的值,必须知道其数据类型。这就是为什么在用C语言定义指针时应该指定数据类型,指示存储数据的内存地址的特定数据类型。
指针和数组之间的关系指针也与数组密切相关。定义数组时,取的名称是指向数组第一个元素的指针,也就是说,要访问数组a中的[0],可以直接访问*a。通过类比,可以通过访问*(a+1),*(a+2)访问a[1],a[2]。这是因为在定义数组时指定了数据类型。因此,这里的+1不是一个简单的加法,而是一个sizeof(a[0])被添加到指针存储的地址中(这里的sizeof用于获取存储期间变量使用的内存大小)。从NicholasTse可以看出,如果每个int类型占用4个字节,那么每次+1都会再次访问内存地址+4。
需要注意的是,以这种方式访问数组会导致数组越界的问题。换句话说,如果定义了长度为n的数组,但n+1位是通过*(a+n)访问的,C语言将不会有任何错误提示,只会返回存储在内存地址中并根据定义的数据类型计算的值。在许多情况下,不可能判断它是否超出范围,因此以这种方式访问时需要小心。
此外,尽管数组名是指针,但它是一个常量,因此不能为其赋值。
字符和字符串如前所述,chartype主要用于表示字符。字符串由字符组成,其底层是由char类型的变量组成的数组。因此,字符串可以通过char*或char[]生成。赋值时,可以通过数组或直接通过双引号逐字符赋值。
在其他一些编程语言中,会有一个数据类型字符串来表示该字符串,但在C语言中不会。因此,字符串的处理相当于字符数组的处理。
在处理字符串时,应该注意数组长度包含最后的0,以及斯特伦功能不起作用。此外,如果以数组的方式逐个添加字符,而不在末尾添加0,则字符串中的数据将是错误的,因为数组是越界的。为了防止这种错误,最好通过双引号直接赋值。此外,无论字符数组有多长,第一次出现的0代表字符串的结尾。
由于char实际上是一个数字,所以在解决大小写转换等问题时,可以用+-32来解决。这里来自ASCII码表,每个数字对应一个字符。代码表在互联网上很容易找到。如果不记得具体的大小,可以通过格式化输出%d直接查看相应的数字。如果不记得大小写和大小写之间的差异是32,可以使用';a';-'A';等它来的时候就凑合着吧。
需要注意的一些语法格式教师可能不会关注语法格式,但事实上,好的格式可以显著提高代码的可读性,促进理解和发现错误。
main函数首先,根据C99标准,main函数应定义为intmain(无效的){...}或者intmain(int-argc,char*argv[]){…}。前者更常用于当前的学习阶段,在这个阶段,空白通常可以省略。然而,最后一次返回是0;可以省略。如果未写入,则默认返回0。有些老师或书可能会写空,或者一定要写返回0;明确地这些都是错误的。具体标准参见标准文件。
main函数定义
上图:main函数的返回值
缩进压痕和直线进给的使用也很重要。{和}应该在一行上,并且包的内容应该缩进一次。此外,不管if语句还是for语句,如果大括号中只有一个语句,许多老师都会去掉大括号,把它写在一行上。这不是一个好习惯。你仍然应该换行,添加大括号和缩进,以便于阅读和后续修改。
您可以使用联机格式,或阿斯泰尔和其他格式化软件来格式化代码。
另一个小tips除了上面老师可能一笔带进来的内容之外,我在编程中还学到了一些小tips:
Warning(敲门代码是一个不容忽视的警告)
我希望所有读过这篇文章并需要学习C语言的学生都能学好这门课程并取得好成绩。
对于那些准备成为一名优秀程序员的人来说,如果你想更好地提高你的核心编程能力(内部技能),让自己成为一名拥有真实素材的强大程序员,你最好现在就开始!C/C++,一种永恒的编程语言~
分享编程学习书籍:
编程学习视频分享:
分类和分享(源代码、项目实践视频、项目笔记、基础入门教程)
欢迎转行和学习编程伙伴。使用比你想象的更多的材料来学习和成长!
如果你对C/C++感兴趣,你可以在后台关注小编的私人信件。我:[编程交流]一起学习!你可以得到一些C/C++项目学习视频资料!关键字自动回复已经设置好了,很高兴自动收到!
最新评论