这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 软件与操作系统 » 【学习会】一起学习C语言之重温C语言

共18条 1/2 1 2 跳转至

【学习会】一起学习C语言之重温C语言

院士
2018-05-11 11:43:05     打赏

从大一后半年接触C语言,一直未曾放下C语言的学习与提高。

C语言的地位就犹如生活中的英语,是一门基础语言,是一门与其它语言沟通的语言。

借论坛活动机会,换一个视角,站在另一个高度重新学习C语言。

相信收获还会满满的。

在为期四周的活动中,温习一遍基础知识,抛弃浮躁的心态,以此帖为根据,记录这段“重温C语言”的时光。


主题帖子更新列表:

1、我的学习计划...... 6楼

2、第一章、格式化输入输出...... 7楼

3、第一章、格式化输入输出实验操作...... 8楼

4、第二章、运算和数据类型...... 9楼

5、第五章、数组...... 10楼

6、第七章、基本数据类型...... 11楼

7、第十二章、结构体(另枚举类型)...... 12楼

第一周的学习顺利完成,我也重温了C语言的这几个基本数据类型,接下来的一周将进行程序编程方面的学习。

8、第三章、分支结构...... 13楼

9、第四章、程序的循环控制...... 14楼

10、第六章、函数...... 15楼

11、第八章、动手编写自己的函数...... 16楼

第二周的学习也顺利完成,对于程序的控制与基本数据类型的应用,完成了温习。接下来一周将学习C语言的精华,字符串与指针!

00、期中作业题...... 17楼

12、第九章、字符串...... 22楼

13、占位符(待添加)





关键词: 学习会     重温     C语言    

院士
2018-05-18 08:54:20     打赏
2楼
我的学习计划

从今天开始,“【学习会】一起学习C语言”的活动正式开始更新。在开始学习之前,列一个学习计划,一方面是学习的进度把控;另一方面也是对学习的一个督促。

从《明解C语言》的目录看,全书分为13章,其编制顺序如下:

  • 1 初识C语言

  • 2 运算和数据类型

  • 3 分支结构程序

  • 4 程序的循环控制

  • 5 数组

  • 6 函数

  • 7 基本数据类型

  • 8 动手编写各种程序吧

  • 9 字符串的基本知识

  • 10 指针

  • 11 字符串和指针

  • 12 结构体

  • 13 文件处理

考虑到自己并非初学者,于是将学习顺序按照内容归类,统一学习,因此我的学习顺序将做如下调整:

1周:第1 初识C语言;第2 运算和数据类型;第5 数组;第7 基本数据类型;第12 结构体;

2周:第3 分支结构程序;第4 程序的循环控制;第6 函数;第8 动手编写各种程序吧;

3周:第9 字符串的基本知识;第10 指针;第11 字符串和指针;

4周:第13 文件处理;

计划好学习内容与进度,下面就部署一下C语言的开发编译环境。本次将依平时常用的IAR嵌入式开发环境为主要编译平台,在特定示例或者学习过程中再考虑其它平台。

现在电子书已经下载完毕,开发环境也搭建完毕,就剩下开始学习了。Let’s go!!



院士
2018-05-19 15:29:42     打赏
3楼
第一章、格式化输入输出

发布时间:

帖子链接:

基本在所有的书本里第一章都是基础, /* 有点废话了 */ 《明解C语言》也不例外。

本章阅读之后主要熟悉了三个函数,分别是 printf函数,scanf函数,puts函数。

这三个函数的具体用法在这里就不再copy人家的原文了,后面会以示例说明,这里就先谈谈其主要目的与应用吧!

1、方便我们了解变量的操作及变量值的改变;

2、将C语言的学习从无形到有形,深入学习C语言;

3、为后续变量与存储的学习提供方便;

在变量跟踪的过程中,现在的开发环境基本都可以单步调试并实时显示变量值及地址,但依然保持这个printf的方法便于记录与实现。

本次我使用IAR cortex-m开发环境,在此环境下完成本章实验并没有过多需要注意的问题,只需要头文件 include <stdio.h> 添加,在输出窗口使用”terminal I/O”窗口查看即可。



院士
2018-05-21 11:19:30     打赏
4楼
第一章、格式化输入输出实验操作

先列出来源代码,如下:

#include <stdio.h>
void main(void)
{
  int i = 12;
  printf("hello world!\n");
  printf("the variable i = \t%d\n", i);
  i = 1234;
  printf("the variable i = \t%d\n", i);
  i = 123456;
  printf("the variable i = \t%d\n", i);
  printf("this is exp01! www.eepw.com.cn);
  while(1)
  {
    ;
  }
}

printf.jpg


在上面的示例里,我们使用了printf函数的输出功能,我们可以看到,在变量的输出上面我们已经完成了格式化处理,使变量看上去清楚、明子,非常便于我们对数据的理解与分析。

在本实验中,使用了“\t””\n”两个转义符,分别代表一个制表位与换行,二者均用来对齐数据输出的,从上面的输出截图也可以清晰看到。

今天的实验为以后的输入与输出打好了基础,继续下一章的学习了。



院士
2018-05-22 13:27:18     打赏
5楼
第二章、运算和数据类型

发布时间:2018522

帖子链接:http://forum.eepw.com.cn/thread/296305/1#9

本章主要讲了一些概念,这些概念在平时使用时非常平凡,以致于多年以后再谈起时对其概念会比较模糊,但确实不影响工作与学习。

运算符:我们最常见的基本运算,如+-*/%

操作数:参与运算的变量或者常量。这个多提一下,在以后的应用过程可能会涉及到左操作数右操作数的概念,我们遇到再了解。

单目运算:从名称上可以得出,只有一个操作数的运算,只有以下四种”“~”“-”“+”(这个仅对应,无实际意义)

双目运算:有两个操作数的运算,如赋值操作;

三目运算:有三个操作数的运算,如表达式:真?假;的运算符;

在本章第二节里谈到了数据类型,在嵌入式编程里对数据类型不是特别敏感,多数是以变量的长度来定义,但不同数据类型对应的字节长度又是编译器依据平台自己制定,这时就存在了概念的交叉问题。举个例子:

对于int类型来说,在VS4字节长度的变量,而在IAR Cortex-M下,只有2字节长度。它们对应的数值大小可完全不同,因此,在C99标准下,引入了另外一个概念,即按字节长度定义的数据类型,如uint8_t 8位无符号型变量。它的数据大小在 0-255之间,其它的数据类型大家可以以此类推。

以上是针对整形数据而言,而在浮点数下,依然使用了float double两种类型(本书中只能使用double类型),两个数据是非常大的,在limits.h的头文件里有定义,这里我就不班门弄斧了。

本文还讲了数据类型转换的问题,在嵌入式编程里,数据类型尽量不要转换,如果遇到小数的情况,建议使用放大倍数来解决。当然,在本章里,我们还是以数据类型转换来完成对应实验。

综上所述,运算和数据类型是我们平时再平常不过的应用,基础知识是知识的基础,而非可以忽略的知识。



院士
2018-05-23 13:17:08     打赏
6楼

第五章、数组


数组在C语言里的应用非常普遍,也相当灵活。教材里对此章讲解较初级,高阶应用估计是留着他的提高篇里讲述了。

先来描述数组,数组是相同数据类型的变量的集合。一定是相同的数据类型。

数组的声明方式也相当简单,即在变量后面添加方括号【】int array[8],里面的值”8”即为数组的长度。在声明的时候数据括号内的数值一定为常量,主要因为C语言不支持变长的数组,换句话说,编译器在初始化时,会以此为该数组分配地址与空间。


int array; /* 声明int类型的变量array */
int array[8]; /*声明int类型的数组array[],数组长度为8 */

数组的引用也非常方便,方括号里的数值称为标号,如array[0],数组第一个元素,记住数组的标号是从“0”开始的。

数组的复制:这个用到的也不同,记录数组的复制是数组内部所有元素的复制,文中也告诉我们,一个变量用一个等号来赋值,而数组要用一堆等号来赋值。

多维数组就是数组的数组,起初可能很难理解,用一两次自然就懂了。

本章还提出了另外一个概念宏定义,宏的应用也是在编译阶段完成的,其是对文本的一个简单替换。为了增加程序的可读性,建议大家在常量的使用时通过宠定义来实现——这个是经验之谈。

对于宏的替换,编译器不会替换字符串字面量和字符常量中的部分内容,也不会替换变量名等标识符中的部分内容,举例来说:

#define AA (0)
#define AAAA     (1)

上面是两个宏,“AAAA”会被替换为”1”,而不是“00”



院士
2018-05-25 17:22:39     打赏
7楼
第七章、基本数据类型

这一章主要还是讲概念,重知识讲解,平时对这些概念基本忽略,而是直接使用的多。

本章讲了进制。十进制,十六进制,二进制,八进制,这些都是数字,其值是相等的,不会因为进制的改变,其实际的数量而改变。它的作用为我们展示与应用数据提供了方便,所以这里举几个典型的应用示例:

有一个2字节长的数,其高8位代表小时数,而低8位代表分钟数,此时为409分,我们就可以轻松表示为0x0409,如果使用十进制1033,我想你肯定很难看出来是几点几分吧。

数据基本类型,在嵌入式编程环境下,主要还是区分整形与字符型,很少使用浮点类型。它们之间的联系非常紧密,因为全部需要存储空间,所以全部可以用存储空间来解释。先说说字符型,

字符型,主要针对ASCII码使用,表示字符,存储空间为1字节,值域范围0~255。我们常用的printf函数参数就是char型。特别说明以下三个标志性字符:

‘0’ = 0x30;

‘A’ = 0x41;

‘a’ = 0x61;

这三个是基准,剩下的字符可以依据这三个推测出来。

整型,该数据类型还有short int, int , long int等,依编译器的不同而不同,字长也是依据编译器而定。总之,2字节长的整形值域范围就 0~655354字节长的,请大家自行计算。

对于整型来说,在平时设计时最关心的还是溢出、有无符号两件事。

溢出:在计算过程中,16位长度还是很容易溢出的,例如对两个整型数据相乘,一不小心就溢出了。还有就是移位操作,大家自行在平时的设计中多留意,我也会在后面的实验设计中再详细讲解。

有无符号:有符号类型,将直接影响了值域范围,另外,有符号类型的数在做移位操作时要多注意。

浮点类型,多数编译器使用4字节长度来存储,与整型数据按位存储不同,浮点数将字长区分为整数区、指数区、小数区等,具体的划分我觉得编译器自己按标准执行吧,这么多年也没有关心与操作过。

本章还讲了优先级的概念,在运算与操作过程中,优先级的概念非常重要。概念非常重要,识别起来要对照那个大表,我表示我平时不会对照表来写代码,比如 *p->head[5] 这个表达式是什么意思?如果写成 *p->head[5])是不是清晰很多,优先级是不是一目了然了。所以,关于优先级的问题,自己在平时写编程时多用几个括号即可完美解决,放弃那个大表吧~~



院士
2018-05-27 18:10:09     打赏
8楼

第十二章、结构体(附枚举类型)


本章是非常重要的一章,结构体的概念与实际意义与C++里类的概念有几分相近,都是是一类相关联数据的集合。用示例来解释会较为清晰,以串口参数为例,串口的配置有许多参数,但基本包括以下4个:1)串口波特率;2)串口停止位;3)串口传送位数;4)奇偶校验位。我们在配置过程如果声明四个变量,在初始化时依次调用——这个思路肯定没有问题,程序也是能成功初始化并跑通。只是这并不符合编程习惯,当然也因为我们有更好的——结构体变量。

结构的声明需要使用struct关键字,示例如下:

struct _tUartParam
{
      uint16_t band;
      uint8_t stop;
      uint8_t frameBits;
      uint8_t check;
};
struct tUartParam uart1;

上面的示例,我们就声明了变量uart1。结构体的变量初始化过程就是对结构体成员每个变量都进行初始化,现在uart1使用波特率96001位停止位,无奇偶校验位,8位字长,示例如下:

Uart1.band = 9600;
Uart1.stop = 1;
Uart1.frameBits = 8;
Uart1.check = 0;

结构体的引用也挺简单的,就是使用“.“号,像上面的示例一样。对于结构体的指针变量,还有另外一种常用的引用方式”->“箭头方式,例如:

struct tUartParam *pUartParam;
pUartParam = &Uart1;
pUartParam->band = 9600;
pUartParam->stop = 1;
……

这一章还讲了typedef关键字,这个也是平时常用的关键字之一。其作用就是声明一个我们自己定义名字的类型,如:

Typedef BYTE char;

这样就声明了一个BYTE类型等同于char型,我们在使用时更加明晰,增强代码的可读性,从而减少误操作的可能性。

还有一个类型“枚举类型”,它只是声明了类型的值域必须为声明的值,不能为其余值,否则会报错。这个典型应用就是有限状态机编程里的状态机的状态值。比如我们生活中最常见的星期表示方法,因为只可能是这七个值,不会出现星期八的情况,因此,枚举值可以完美处理这样的需求。

声明方式:

enum eWeek {SUN, MON, TUE, WED, THUR, FRI, STA};

枚举类型的变量,编译器最后仍然是处理成为整数变量,换句话说,可以对枚举类型的变量进行运算操作,但是我们如果没有特殊要求不要这样设计,建议仅使用赋值语句来实现变量的变更。



院士
2018-05-28 22:56:30     打赏
9楼
第三章、分支结构程序


今天学习程序流的控制方式,主要有if语句,switch语句,while语句,for语句。在本章里,我们要学习前两个,先来第一个if语句。

If语句,判断语句,像它的英语意思一样。一个完整的if语句如下所示:

If(表达式)
{
  执行语句0;
}
Else
{
  执行语句1;
}

表达式为真是则执行语句0,为假时,执行语句1 。这个并不难理解,平时使用时要注意以下几点:

表达式为真,如果表达式为值,则真为非0,而0为假。例如,空指针的值为0,即为假条件。

对于假条件,在没有执行语句1时,其是可以省略的,即只有if语句,而没有else语句,这个我们在平时的源代码阅读中经常看到。

If语句也是可以嵌套的,在if判断成功后再判断if的条件。其实可以一直判断很多条语句,就像switch语句那样。

Switch语句,在分支结构另一个典型语句设计,这个我们将在下一章的学习中进行了解。



院士
2018-05-31 00:00:46     打赏
10楼

第四章、程序的循环控制

我们在讲述第四章之前,我们先将上一章遗漏的switch语句搞定。

对于switch语句,分支结构语句,其部署的方式如下所示:


Switch(变量值)
{
Case 常量0:
{
  语句0;
}
Case 常量1:
{
  语句1;
}
Default:
{
  语句N;
}
};

其实本质上,switch语句,就像书中所言,switch语句可以用if来改写,只是这一步编译器帮我们做了而已。

Switch语句在应用中所占比例相当高,主要由于其清晰的程序设计格式,尤其在有限状态机的应用上面,二者在一起就像是郭靖与黄蓉。

这里有一个小小的提示,在使用switch时,一定要将出现概率大的常量放在前面。

讲完分支结构,我们再来看看循环语句。Do{语句段}while(表达式);或是while(表达式){};或for(前执行语句0;表达式0;后执行语句1)这三种方式。从上面的文字与程序格式,我们可以得出来循环中有几个要素:循环的初始条件;循环主体;循环终止条件;随着学习的不断深入,对于元素可有可无,也促成了一些专有应用程序。

我们先来说说Do{语句段}while(表达式);它的程序结构里没有初始值,如果要有需要初始化变量,则初始值需要放在循环语句外。“Do”即做为循环起点的标识,然后执行语句段,再执行while语句内的表达式,即判断循环结束。

        这里一定要说明一下,使用do{}while();语句至少要执行一次循环体,即如下的示例代码情况下,仍然会执行一次。

do
{
执行语句0;
}while(0);


    while(表达式)语句则是要先判断表达式的真假,如我们常用的无限循环语句while(1)语句。因为表达式一直为真,因此,其主体会一直循环执行下去。

    for语句在自增运算的时候,也是非常方便的——我觉得主要因为其代码的清晰性,从实现的角度,能用while语句实现的,肯定使用for语句也一定可以。

比如我们最常用的批量赋值语句:

for(i = 0; i < 10; i++)
{
  a[i] = i;
}




共18条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]