读者在这个时候了解这么多已经够了

  新闻资讯     |      2024-04-25 10:36

  我们的C语言教程旨在打造一个有深度、有头有尾、系统性、公开免费的C语言教程。同时,也欢迎大家来提出批评指正意见。

  关于专栏介绍,可以参看这篇文章呀零基础C语言自学教程正式开更!! - 知乎

  本节内容,是接着我们上篇的内容来进行介绍,是初步认识C语言的全部知识框架的下半场呦~~~

  当然,如果还有没有安装环境、不会安装环境的同学,我们也为其奉上了完备的安装教程呦(含VS及VScode):

  如果你觉得我们村子的文章内容很好,也可以选择收藏再看、防止找不到了呦~~~

  【若要看原文,请移步微信公众号【自学编程村】,那里的排版可能比这好看些零基础C语言自学教程(1)——初步认识C语言的全部知识框架结构(下))】

  (2)讲了C语言的程序框架,写出了第一个程序——hello world。

  (3)数据类型。包含数据类型的创建、使用,我们着重讲了数据的输入和输出。还讲了数据类型的大小,即每种数据类型占据多少个字节。

  (4)常量和变量。重点讲了变量的分类、作用、生命周期;四种变量的类型。

  (5)数组。主要讲了三点,分别是数组的声明;数组的初始化;数组的访问。

  (6)字符串。每一个字符串后面都跟着一个\0,注意到strlen和sizeof的细微差别,一个是把\0计算上的,一个没有计算上。

  (7)转移字符。重点记忆的那几个:\\,\n,\t,\ddd,\xhh等。

  如果你对上面的知识还有比较陌生的话,建议你再重新看下。我把链接再贴一遍哈~~~零基础C语言自学教程(1)——初步认识C语言的全部知识框架结构(上)

  那么接下来,我们就要介绍下半部分的内容了,即:初步认识C语言的全部知识框架结构(下)。

  选择语句,一般来说有switch和if两种比较常见的选择语句的形式。我们今天还是点到为止,只介绍一下if的选择语句。

  (ps:为了增加体验感,我讲我原本放在其他网站上的图片均做了脱敏处理哈)

  这里的else if也不一定要有,如果只是A和B中间的选择,直接用if - else就行。

  ps:如果按照标准画,输出框应该用平行四边形,但是我的画图板好像找不到平行四边形,就凑合着看吧哈哈哈,明白意思就行~

  如果我想输出10句hello world,难道我要打10个printf吗?有没有更好的办法呢?

  先说一下,循环语句体中,共有三种主要循环方式,分别是for循环;while循环;do while循环。今天在这里,由本章的定位所决定,我们只是简单了解一下它们,我们只简单的介绍一下while循环(还有一个原因就是如果今天都讲了以后就没有内容写了哈哈)

  这就是循环语句的功能。这里我们用的就是while循环。while循环的循环过程是这个样子的(我们用上图的例子来分析)

  所以说,循环就是重复的执行一件事情,直至满足了某些条件,才可以跳出循环。

  我们先讲一下前两种,后两种我们放在底下的结构体知识里面来说(往下翻,在下面讲到)。

  比如,我们上面在说数组时数组的访问是通过array[2]来实现的,这里的[ ]就是下标引用,可用于数组访问。

  同样的道理,我们在说函数的时候讲到写一个函数的名称然后在后面打括号,这里的括号就是我们所说的操作符.

  1、提一嘴,%表示取模。就是取余数。比如5%2=1;需要注意的是,%不可以用于小数的运算,只能用于整数(用专业的话说,只能用于整型)

  (1)倘若除号 / 的两侧都是整数(整型),那么其所得到的结果也是一个整数。比如5/3,最终的结果只留整数部分,也就是说结果是1。注意这里不是四舍五入,而是将小数部分全部舍去。

  (3)而倘若除号左右两边有一个数是浮点类型,一个是整型,那么所得到的结果就是一个浮点数。因为在进行运算的时候,会将你的整型(如int型)强转为浮点型(如double型),然后进行 double类型/double类型 的运算。结果自然而然就是一个小数。

  为什么会发生强转?理由很简单,只有相同的类型才能够进行算术运算。而double的等级比int高,所以是要int往double转(等级关系一般为char short int float double),这个等级关系很好理解,因为如果不是这样,在转换的过程中,会造成数据丢失(比如如果是double往int转,那小数点后面的值岂不是就丢失了)。

  我们之前介绍过,数据使用二进制存储,一个0或者1占据着一个比特位。而且一个整型有4个字节(32个比特位)。那么, 和 是在二进制上进行的操作,其中代表左移,代表右移。

  (注意下前面的&、、^都是对两个数操作然后得到一个新的数,比如3&5,35等等。而~是对于一个数进行操作的,比如直接 ~3、~1等)

  &的规则:两个数的某一位(指每一个0或者1这样的比特位)都为真,得到的这一位才是真。

  实际上,这个数就是-3。至于它为什么是-3,这和计算机中数的存储有关系,我们以后再讲。

  两边的条件必须都为真,if判断才为真,否则一假即假。这就和我们高中所学的这个很像:∩(也是表示并且)

  那么我们上面的条件判断的最终结果就为假喽。因为1是不大于2的;12该语句判断为假,那么整条语句的判断都为假。

  (3)需要注意一点的是,编译器在进行条件判断的时候,是从左向右依次进行的。

  那么就是说,对于表达式:1 2 && 4 3,左边的1 2已经为假,那么编译器根本就不会去执行右边的4 3,因为它知道一假即假,即使右边为真,整个结果也为假,再去执行就没有意义了。所以它就进行了一个优化:倘若 && 左边的表达式为假,那么就根本不会去执行 && 右边的表达式。

  也是同样的道理,由于其判断的条件是一真即真,所以如果左边的表达式的结果为真半岛全站APP,那么编译器也就不会去执行右边的代码了,直接返回真。

  = 的意思不是等于,而是赋值。像a=3;这样一条语句,是说把3的值赋给a;

  接下来a = a + 1,表示把a + 1的值赋值给新的a。这个时候,a的值就变成了11。

  a += 10,它的含义就是自增10,它的等价的语句实际上就是:a = a + 10。所以现在a的值变成了21。

  a -= 20,同理,即让a的值减等20,等价的语句实际上就是a = a - 20。所以现在a的值就变成了1。(由21-20得到)

  a /= 3,等价于a = a / 3,注意是整除,所以最后a变成了0。

  我们首先需要明确一点,一个关系表达式,再判断完之后,是会有一个返回值的。即假为0,线)

  这里的sum==30就是判断是否相等的语句。意为:如果sum等于30,那么输出hehe;否则,输出haha。

  (2)那么我们以同样的逻辑来理解!=就比较简单了。!= 意为不等于。(如下图)

  如图,这是,我们输出的应当就为haha了。因为sum就是30,判断语句sum!=30为假,那么进入else语句中,打印haha。

  先执行右边的5 3(因为它们的优先级更高,我们以后会说),条件为线),然后将返回值赋值给a。

  所以最终这里的结果应当是一个非零的值,一般为1(但需要注意绝不是只能为1)

  ps:表达式的含义可以理解为由数(或者字符)和操作符连接起来的式子。比如5+3是表达式,53也是表达式,5 3也是表达式。一个i,一个j这样的变量,或者一个数字,一个字符也都可以是表达式。由关系操作符连接起来的表达式为关系表达式,它有真有假,但都是表达式。

  结合上面所说的,a b为真吗?答:为假。所以返回b,所以上式等价于:

  因为a为非0,为真。那么!a就变成了假,if里面的就进不去啦,所以就不能输出haha了。

  这两个合为一组来看。需要注意一下,这两个可以作为单目操作符,就是在一个数前面加个+ - 。比如,3我可以写成+3(不过得到的结果一样的效果)。我也可以写成-3(就变成了一个负数)。很好理解的。

  这与上文所说到的strlen很像,但又不完全相同(后面的章节会具体说到二者的联系和区别)。它是一个运算符,其作用是取得一个对象(数据类型或者数据对象)的长度(即占用内存的大小,以byte为单位)。我们在前面计算数据类型的大小的时候用到了它。

  比如,我原本i是5,我现在i++;那么i就变成了6,它等价与i = i + 1;同理,如果i--就变成了4(i原本是5的情况下)。

  在打印第一个a的时候,先将a自增,再打印出来。所以,打印到屏幕上的数为10+1=11。

  在打印b的时候(看第二个printf),++为后缀,那么遵循先使用,后加加的原则。先使用则打印出来,打印出来的数就是20;然后再自增。我们这个时候再次打印b的值,发现它已经变成了21。这是因为其在上面打印后++的缘故。

  就是在一个类型的前面加上一个括号后,把原来的数据类型强制转换为括号里面的数据类型。

  只不过需要注意的是,经过(float) a这样一条语句执行强转后,a的值仍然为int不变。理由很简单。我们的强转,是对于数值操作的结果,而不是对变量操作的结果。我们是先把a的值拿出来,然后把它强转为float,但是并没有改变a的类型。就好像有一碗水,你泼出去一点,泼出去的可能弄脏了,但是留在碗里面的还是好好的。泼出去的水就好像取出a的值并对a的值进行了强转,放到某一临时区域内。但是变量a本身的类型是不变的。

  关于操作符,我们知道了除了单目操作符,还有双目(比如*;/等等)、三目操作符(exp1?exp2:exp3),只不过这些操作符我们都在上文提过了。然后还有就是关于运算符的优先级的问题,算术运算符 关系运算符 && 条件操作符 赋值运算符。

  进一步详细地介绍我们会放在后面的操作符详解的章节中继续为大家介绍。关注我的文章更新(可以关注公众号、收藏)哈~~~~具体我们以后再提。

  关于操作符,读者在这个时候了解这么多已经够了,因为本章我们是初始C语言。

  我们挑几个来说说(所有的我们都会讲到,只不过有的我们已经在上文提到,有的将会在下文讲解时提到,现在我们挑几个来专门说说)

  break是用于终止所在的循环。而continue是指跳过当前的一次循环。

  (提示一下下面的while(i),i也是一个表达式,同样遵循零为假,非零为线的时候,就为假,就跳出while循环)

  (再次提示一下下面的while(i),i也是一个表达式,同样遵循零为假,非零为线的时候,就为假,就跳出while循环。因为有许多同学竟然在这个地方有疑问,特此解释)

  我们首先铺垫一下,我们在写代码之前,会有创建一个新项目(或者选择一个现有的项目)这样的选项,就是打开一个项目(也叫工程project)。然后在一个大工程下面,我可以创建许许多多的.c文件或者其他文件。

  那么,我在同一个大项目下(即一个大工程下)如果有多个文件,用extern声明后,我在这个文件里面定义的变量或函数,可以在另外一个文件里面去用。

  如图,我创建了两个源文件(创建方法简单来说,就是解决方案资源管理器-源文件-添加新建项-...)(具体这个怎么创建,看VS的安装及使用这篇文章:C/C++环境配置(VS的安装及使用))

  我在一个文件中写了add函数的具体实现,在另外一个文件中如果直接调用add,肯定会报错。如果,我们加了一个extern,就不会报错了。

  根据报错,意思是add无法解析,编译器不知道它是什么。说明我们在add.c中的函数不管用了。这是因为static修饰的缘故,使得add.c中的函数add无法作为另一个文件的外部链接来使用。也就是说,我加了static,我的函数只能在我的这个文件中用。别的文件想用,就不行了。

  和修饰函数其实一样的道理,就是让其无法在外部被使用(即同一个项目的其他文件使用),实际上是在链接这一步的时候断了(关于链接操作,我们以后详谈)。

  (再次再次最后提示一下下面的while(i),i也是一个表达式,同样遵循零为假,非零为线的时候,就为假,就跳出while循环,这是第三次提示了呦~)

  因为当a被static修饰后,再次进入print函数的时候,便不会再次创建。可以通俗的理解为:成为了一个静态的量。

  所以,a++会被一直执行,但是int a=1却会跳过了。它只会被创建一次。

  至于其他的关键字,我们会陆陆续续讲到,读者只需要在我们以后讲到这些东西的时候,知道它是关键字就可以了。

  既然是在内存上的操作符,那么了解指针之前,我们就有必要来了解一下什么是内存。

  (1)首先,内存可以理解为一块一块连续的区域,用于存放数据使用(如下图)。

  像上图那样,可以理解为当我在创建的变量时,我需要向操作系统申请一定大小的空间,

  可以看到a的数据为 0a 00 00 00因为是16进制,0a刚刚好就是表示16(后面的0表示高位,相当于十进制中的百位千位等,这个我们以后再说,总而言之不用管,不会影响我们得出结论),在这里,我们以肉眼可见的方式看到了a的地址:(如下图)

  a的地址现在我们已经拿到了,是0x00AFF7C8,那么,这个地址就是指针,它存储着a这个变量的值。也就是说,0x00AFF7C8就是变量a的指针。

  那指针变量是个什么东西?通俗的来说,就是用来存放指针的。就是存放0x00AFF7C8这个地址的。我们用 * 来表示。

  不过,我们在日常的描述中,其实指针和指针变量之间并没有那么严格的区分,就是大家也普遍接受并习惯 在说指针的时候,代表的就是一个指针变量。这里大家心里面有个数就好。

  (2)&a(注意,这个时候取地址的作用就显现出来了,这里就是意为取出a的地址),即取出a的地址。

  那我现在想要访问指针变量里的地址所存储的数据,我应该怎么办呢?那就应该用解引用操作符。解引用操作符依然是 * 。它是这么用的。

  ①*p表示对指针变量p进行解引用。就是说用我拿我手里的指针变量p,找到指针变量p所存的地址,通过这个地址来访问其存储的数据的值。

  我们暂且就先介绍这么多,我们这次先来简单认识一下指针,读者在此只需要知道指针是什么,怎么创建、怎么解引用就可以。

  到后面的指针详解这一章节的时候,笔者会为大家详细的介绍有关指针的所有内容。

  我们在说数组的时候,明确强调过,必须时相同的类型才可以放在数组里。那么不同类型呢?可以这样理解,对于不同类型,我们就放在结构体里面。

  结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。

  这里的struct pep就是结构体,它也是一种类型。就好像我们之前说的int,char一样。它属于自定义类型。

  然后,在大括号里面创建上我们想要创建的类型。在这个大括号里面,可以创建不同的类型,比如int, char 等。

  看,像这样,我们就创建了一个结构体变量a,可以理解它的类型就是struct pep。

  在这么一个结构体中,我们对其中的四种类型分别进行了初始化。(注意要对应)也就是说,变量a里面的20就相当于age类型。2121212就相当于是char类型的数组,存放在以数组名为tel的数组中。其它同理。

  这个时候,就用到了我们之前跳过去没有说的两个操作符: . 和 -。(二者用一个就行)

  ps : 同学们在变量命名上、括号{}的书写上按照我们图片上的来就可以,关于代码命名、格式规范,我们在讲完一定的知识点后会系统的为大家介绍一下。

  现在,我们就要求同学们照着葫芦画个瓢就可以。如果你照着葫芦画个瓢不行,你照着葫芦画个葫芦都可以~~~

  3、条件操作符;分别有下标引用、函数调用等操作符,算数操作符,移位操作符,位操作符,逻辑操作符,赋值操作符,关系操作符,条件操作符(也叫三目操作符),以及一些单目操作符。主要要求在见到能够认识,不要求熟练掌握。

  4、关键字介绍;主要介绍了auto、extern、static、define、break、continue、typedef等操作符的简介。

  如果觉得文章好,那就动动你的手指,给予一下精神上的鼓舞吧哈哈(点个小赞什么的hhh)

  好啦,最后想说,码字不易,如果觉得对你有帮助,就点个赞或者给@自学编程村个关注呐,笔芯~~~