Linux一站式学习C语言学习笔记

1.1程序和编程语言:(2019.2.16)
计算机是由数字电路组成的运算机器,只能对数字进行运算,符号/声音/图像等信息在计算机内部也使用数字表示的,这些数字经过专门的硬件设备转换成对应的信息。
程序由指令组成,指令通常包括:输入/输出/基本运算(加减乘除和数据存取)/测试和分支(判断)/循环;编写程序即将复杂分解为简单,以至于能够用以上指令来完成。
语句是计算机指令的抽象表现,编程语言分为低级语言(机器语言和汇编语言)和高级语言(c,c++,java,python等 用语句编写);机器语言(顾名思义即计算机能够读懂的语言)由十六进制数字组成,将这样一组组数用助记符表示(汇编语言),汇编器起的作用即将助记符翻译为对应的机器语言;
C语言中的语句和低级语言的指令之间不是简单的一一对应关系,一条语句可能翻译成多条机器指令(编译),由编译器完成。C语言优点:可移植的(指一个程序在不大改的情况下可以在不同平台下运行),平台无关的。平台,可以指计算机体系结构(指令集/机器语言),操作系统,开发平台(编译器等)。
编译执行的过程:源代码(XXX.c)经过编译器编译(不执行,只是翻译为机器指令)加上一些描述信息生成一个新的文件(XXX.out)称为可执行文件,可执行文件由操作系统加载运行,计算机执行该文件中由编译器生成的指令。
解释和编译:解释即边翻译边执行,而编译是先翻译为机器语言后在执行。


1.2自然语言和形式语言:(2019.2.16)
自然语言:人类讲的语言,可能存在歧义/冗余/隐喻等;
形似语言:为了特定应用而人为设计的语言(数字/运算符号/分子式/编程语言),形式语言必须精确,不能存在上述自然语言的特点。读程序时,学会分解结构,识别符号。


1.3程序的调试:
错误(Bug)调试(Debug)
编译时和运行时的区别:编译时即编译器将源代码翻译为机器码,运行即对应出现黑框(输入数据或不)后得到结果的过程。


2.2常量:
常量包括字符常量(char)、整数常量(Int)、浮点数常量(float)和枚举常量。字符常量要用单引号括起来,例如‘N’,单引号只能括一个字符而不能像双引号那样括一串字符。
printf(格式化字符串,),“5”是字符串字面值,‘5’是字符,5是整数。在格式化字符串中表示一个%需要用“%%”,和\有相似的规律。


2.3变量:
变量代表的是计算机存储器中的一块空间,可以保存一个可以变化的值。
变量的类型决定了它所占的存储空间(而不是变量的内容),C语言中的声名有变量声明、函数声明、和类型声明三种。如果一个变量声明要求编译器为它分配存储空间,那么这个声明同时也是变量的定义。
变量名只能含有字母、数字、下划线,而且只能以字母或下划线开头,一般要避免以下划线开头。


2.4赋值:
**定义一个变量,就是分配一块存储空间并给他命名;给一个变量赋值,就是把一个值保存到这块存储空间中。**变量的最小存储单位是字节(Byte),在C语言中char类型变量占一个字节,其他类型的变量占多少个字节在不同平台有不同规定(chapter 14)


2.5表达式:
参与运算的常量和变量称为操作数,由运算符和操作数所组成的算式称为表达式,任何表达式都有值和类型两个基本属性 ,括号的优先级最大。
向上取整(Ceiling):进一法;向下取整(Floor):去尾法,C语言中无论正负都是把小数部分截掉。


2.6字符类型与字符编码:
每个字符在计算机内部用一个整数表示,称为字符编码,最常用的是ASCII码(取值范围是0~127),char类型本质上就是整数,把char和int统称为整数类型或整形。字符也可以用ASCII码转义序列表示,如\加上1-3个八进制数字,或\x加1-2个十六进制数字,可以用在字符常量或字符串字面值中。


3.1数学函数:
log(在C语言中log即表示数学中的ln)是函数,1.0是参数,log(1.0)是函数调用。
程序第一行的#号和include表示包含一个头文件,后面尖括号中就是文件名(这些头文件常位于/usr/include目录下。)头文件中声明了我们程序中使用的库函数,XX头文件声明的XX库函数。
C标准库(不是库函数)定义了一组标准头文件,每个头文件中包含一些相关的函数、变量、类型声明和宏定义,要在一个平台上支持C语言,不仅要实现C编译器,还要实现C标准库,才算符合C标准。但很多单片机的C语言开发工具中只有C编译器而没有完整的C标准库。


3.2自定义函数:
main函数的特殊之处在于执行程序时它自动被操作系统调用,除了名字特殊外与其他函数没有区别。C89要求所有声明(目前来说就是定义)都要写在语句之前,而C99则允许按任意顺序排列。(总归要现在要一直遵循先声明后使用的原则)。
return 0 表示若程序执行成功则给操作系统返回0,若出错则返回一个非零值。读代码不建议从上顺序往下读,从main函数开始逐步分解每一部分。
如果调用函数时参数列表为空(括号内无参数),并且缺少函数原型,则编译器根据隐式声明规则认为参数类型是void。


3.3形参与实参:
如果要写一个非定义的函数声明,可以只写参数类型而不写参数名,例如:
void fun(int,int);形参:函数中的参数如fun(int a)中的a,实参:传一个参数a给函数,即调用函数是传入的参数;调用函数传递参数的过程相当于定义形参变量并用实参的值来初始化。可变参数:参数的类型不确定;有时候我们把函数称为接口,用函数就是使用这个接口。

Q1:定义一个函数increment,它的作用是把传进来的参数加1。例如:

void increment(int x)
{
x = x + 1;
}

int main(void)
{
int i = 1, j = 2;
increment(i); /* i now becomes 2 /
increment(j); / j now becomes 3 */
return 0;
}

我们在main函数中调用increment增加变量i和j的值,这样能奏效吗?为什么?

A:不奏效,因为调用时传进去的是一个值(一个数值),无论在fun内如何变都只变的是fun内对应的变量的值,与外面的变量无关。除非传进去一个地址比如fun(int *a),那么就明确到某一个位置固定的变量,这样对其修改即奏效。


3.4全局变量、局部变量和作用于:
局部变量:函数中定义的变量,形参也是一种局部变量;
“局部”的两层含义:1.一个函数中定义的变量不能被另一个函数使用,同名或不同名变量均是,代表着不同的存储单元;※2.局部变量在每次函数调用时分配存储空间,在每次函数返回时释放存储空间;
全局变量:定义在所以函数体外,在程序开始运行时分配存储空间,在程序结束后释放存储空间,在任何函数中都可以访问全局变量;
全局变量的作用域从定义的位置开始知道源文件结束,而main函数局部变量的作用域仅限于main函数之中;
全局变量只能用常量表达式来初始化,而局部变量则随意,例如double pi=cos(-1.0),不能这样初始化一个全局变量,初始值必须保存在编译生成的可执行文件中,因此要求初始值必须在编译时就计算出来,然而上式必须在程序运行时调用cos函数才能得到。
未初始化的局部变量的初值是不确定值;C语言不允许嵌套定义函数。


4.1 if语句:
这种控制流程称为分支;运算符两边的的两个操作数应该是相同类型的,两边都是整形或者都是浮点型可以做比较,但两个字符串不饿能做比较,在以后会介绍;==和!=称为相等性运算符,其余(大于小于)称为关系运算符,相等性运算符的优先级低于关系运算符; 一个单独的;号表示一条空语句;{}为一个语句块,语句块内也可以定义局部变量,如{int i=1;}每次进入语句块时为变量i分配存储空间,每次退出时释放i的存储空间;语句块中的变量i和函数的局部变量i是两个不同的变量,因此两次打印的i值是不同的;语句快中的变量j在退出语句块后就没有了,因此最后一行的printf不能打印j,语句块不一定非得用在if语句中,单独使用语句块通常是为了定义一些比函数的局部变量更“局部”的变量。(写代码检验成立)
程序示例:

void fun(void)
{
int i=0;
{
int i=1;
int j=2;
printf(“i=%d,j=%d\n”,i,j);

}
printf("i=%d\n",i);  /*在这里不能输出j*/

}

4.2 if/else 语句:
else总是和它上面最近的一个if配对


4.3 布尔代数:
逻辑与&&,逻辑或||,逻辑非!,关于逻辑运算的数学体系称为布尔代数,在编程语言中表示真和假的数据类型叫做布尔类型,在C语言中通常用Int型来表示,非0为真,0表示假;如果记不清楚运算符的优先级一定要多套括号。


4.4 switch语句:
C语言规定各case分支的常量表达式必须互不相同,如果控制表达式不等于任何一个常量表达式,则从default分支开始执行,通常把default分支写在最后,但不是必须的。
注意:1.case后面跟的表达式必须是常量表达式,这个值和全局变量的初始值一样必须在编译时计算出来;
2.case后面跟的必须是整形(int/char)常量表达式;
3.进入case后如果没有遇到break语句就会一直往下执行,后面其他case或default分支的语句也会被执行到,直到遇到break;


5.1 布尔函数:
C语言的传参规则是Call by Value,按值传递,现在我们知道函数返回值也是按值传递的,return x,返回的是x的值而非变量x本身,因为变量x马上就要被释放了。

习题:编写一个函数double myround(double x),输入一个小数,将其四舍五入(可利用math.h中的ceil向上取整和floor向下取整);

#include<stdio.h>
#include<math.h>
double myround(double x)
{
	if(x>0)
	{
		if(x-(int)x>=0.5)
			return ceil(x);
		else
			return floor(x);
	
	}
	if(x<0)
	{
		if(fabs(x-(int)x)>=0.5)
			return floor(x);
		else
			return ceil(x);
	
	}

}

void main()
{
	double x;
	scanf("%lf",&x);
	printf("%f",myround(x));

}

5.2 增量式开发:
尽可能复用以前写的代码,避免写重复的代码,封装就是为了复用,把解决各种小问题的代码封装成函数,在解决第一个大问题时可以用这些函数,在解决第二个大问题时可以复用这些函数;解决问题的过程是把大问题分解成小问题,小问题再分解成更小的问题,这个过程在代码中体现为函数的分层设计,distance和area是两个底层函数,解决一些很小的问题,而area_point是一个上层函数,上层函数通过调用底层函数来解决更大的问题,底层和上层函数都可以被更上一层的函数调用;
如果对某条代码不确定,可以用printf把其值打印出来看看,检验程序算的对不对,这些检验性语句起到了脚手架的作用,辅助盖房子,而scaffold可以将其注释掉,这样如果以后出了新的Bug又需要跟踪调试时,可以把这句重新加进代码中使用,这种思想叫“增量式(Incremental)开发”。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值