符号语言=汇编语言:指用一些英语字母和数字表示一个指令
低级语言:面向机器的语言,不同的机器间不适用
目标程序:写的高级语言经过编译程序编译为计算机能看懂的二进制文件(目标程序)
非结构化语言:难以维护,难以阅读的较少规范的早期语言(结构化语言解决这个问题)
一个C语言文件的执行顺序:编译器将代码转变为计算机可识别的语言(目标程序vc中为.obj后缀文件)。链接器将目标代码和启动代码(其他源文件)和库函数一起合成可执行代码(可执行程序.exe文件)
结构化程序设计方法:(1)自顶向下;(2)逐步细化;(3)模块化设计(函数);(4)结构化编码(基本逻辑结构)
三种基本结构:顺序,选择,循环
不能在main函数中定义和声名函数
—有效的名称:大小写,数字,下划线。第一个字符必须是字母或者下划线(c区分大小写)
—地址不是左值(不能作为左值),左值是一个可以修改的值,指针可以作为左值
储存期:静态储存期指对象在程序执行期间一直存在,文件作用域(全局变量)对象具有静态储存期
块作用域的对象具有自动储存期,即当程序退出这个块是就释放这些变量占用的内存,自动储存期的对象被储存在栈中,如果对象所需内存过大,栈可能储存不下,可能出现错误
当在外层定义了一个变量x而又在内层定义一个新的x时,当程序运行到内层x处时外层的x会处于隐藏状态(即内层x暂时覆盖外层x),直到内层x消失
static修饰的变量具有文件作用域
0=48 a=97 A=65 int范围-32768~32767
函数可以嵌套调用 C语言中非0则为true
重复定义static修饰的变量不会改变值? 不会.即重复执行static int a=4语句不会重新创建变量和地址
常量:指数:1.25e3=1.25*10^3 。 -0.25e-4 = -0.25 10 ^ -4 e=E,e/E之前必须要有整数
常变量指const修饰的变量
只有整型(包括字符型)数据可以加signed或unsigned修饰符,实型(浮点数)数据不能加。
规范化的指树形式,将浮点数写成指数形式,例:51.236写成0.5123610^2
float a=3.14159f //把此3.14159按单精度浮点常量处理,编译时不出现“警告”。
long double a =1.23L //把此1.23作为long double处理
数据类型的主动转换:浮点型–整形:舍弃小数部分
字符类型=ASCII码。将一个占四个字节int类型赋值给占两个字节short或1和字节的char会发生截断
例:int a=289;char b=‘e’;b=a;,则结果b=‘!’ 即b的ASCII码为33
289转为二进制为100100001.char类型阶段后八位,所以b=00100001=(int)33
(整型变量的最高位代表符号)(100100001=-33 ?)
表达式表达式相当于一个变量,变量能用的地方,表达式也能用(赋值语句是一条语句,包括;)
例:printf(" %d" ,a=b); 相当于a=b;printf(“%d” ,a);
if((a=b)>3){} 相当于a=b; if(a>3){}
表达式也有自己的值,也可以作为表达式,例:a=(b=5)相当于b=5;a=b
赋值表达式是自右向左的结合顺序,所以a=(b=5)等价于a=b=5 (逻辑表达式自左向右)
表达式的值默认取整 (即若x=1,y=2。则x/y的值为0 x+x/y 表达式的值为1)
能return(a,b) //,实际return的是b,因为逗号是从左向右执行的,是顺序运算符号,执行到b,并返回b 即(a,b)返回的是b
1/3 1/3.0 1.0/3 这三个表达式的值分别是多少 分别是0 0.3333… 0.3333…
说明只要操作数有一个是浮点数,结果都是浮点数。float(1/3)的值是 0.00000说明类型转换在括号内就已经发生
表达式a=9的值为9
o = (t = 1, t = t+5, t=t+1);相当于 o = (t = 1, t = t + 5, t); t = t + 1; 结果:o为6
运算符
逻辑运算符 && 与(一假则假,全真为真) ||或(一真为真全假为假,) !非
c>a十b等效于c>(a+b)(关系运算符的优先级低于算术运算符)
a>b==c等效于(a>b)= = c (大于运算符>的优先级高于相等运算符= =)
a= = b
关系表达式的值是一个bool类型
max=(a>b) ? a :b;
赋值号右侧的“(a>b)?a: b”是一个“条件表达式”。“?”是条件运算符。
如果(a>b)条件为真,则条件表达式的值等于a;否则取值b。三目/元运算符
for循环中三个表达式都可以省略,(不能省略分号)
printf(“//ddd”); 双引号中的注释符号不起作用,即依然会输出//ddd (/**/也一样)
“格式控制”是用双撇号括起来的一个字符串,称“转换控制字符串”,简称“格式字符串”。它包括两个信息:
格式声明由“%”和格式字符组成,如%d、%f等。它的作用是将输出的数据转换为指定的格式然后输出。格式声明总是由“%”字符开始的。
普通字符。普通字符即需要在输出时原样输出的字符。例如上面printf函数中双撇号内的逗号、空格和换行符,也可以包括其他字符。
“输出表列”是程序需要输出的一些数据,可以是常量、变量或表达式。
printf(“%d %d\n”,a,b) //a,b是输出表列(即要输出的变量)
%c输出字符时先将字符转为ASCII码再输出
用%f输出实数,只能得到6位小数。
printf(“%20.15fn” ,a/3) //表示一共输出20位,其中15位小数
运行结果:0.333333333333333 注意在0的前面有3个空格。这时输出了15位小数。
%e指定以指数形式 例321.234 输出为3.212340e+002 默认小数点后6位,e+的后面输出3位
只有X,E,G可以大写
scanf("a=%d,b=%c,&a, &b);//在输入数据时,应在对应的位置上输入同样的字符。即输入 a=1,b=3
在输入时若遇到非法字符会认为是输入结束,例输入12c 则a=12,b=c
在使用putchar时,输入字符B后马上按Enter,再输入字符О,按Enter。立即会分两行输出B和O。
输入的是B和换行符和O
注意:执行getchar函数可以获得在屏幕上无法显示的字符,如控制字符。
//函数的返回类型不能是数组,但可以是指针类型
实参是调用时传入的参数,形参是函数体中对实参的使用
void print(int ,float ,char );//这也是正确的(声明一个函数)
“分程序”或“程序块”。
如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件结束。在定义点之前的函数不能引用该外部变量。如果由于某种考虑,在定义点之前的函数需要引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”,表示把该外部变量的作用域扩展到此位置。有了此声明,就可以从“声明”处起,合法地使用该外部变
extern也可以引用在其他文件定义的变量(优先在本文件找)
(但若该变量被static修饰,则extern也引用不到该变量)
把建立存储空间的声明称定义,而把不需要建立存储空间的声明称为声明。
只要不是传入的地址,任何变量作为参数时,即在函数体内的地址都和他在外面的地址不一样,在函数体内改变值都不会带回
main函数中参数的使用
int main( int argc,char * argv[]) //argc和argv是随便起的名字
通过命令行向main函数传递参数,argc是参数的数量,argv存储参数信息
例:一个保护main函数的可执行文件file1.exe 若想传递两个参数bei jing
则命令行输入 file1 bei jing 即可,一个文件名和两个要传入的信息,他们中间有一个空格,文件名也被计入参数数中,即此时argc=3 argv有三个元素(file1 bei jing)
p-calloc(50,4); //开辟50×4个字节的临时分配域,把起始地址赋给指针变量p
realloc(p,50); //将p所指向的已分配的动态空间改为50字节
static 一个标识符,作用1:使被标识的对象成为内部链接的对象 2:使被标识的对象具有静态储存期
extern 一个标识符,声名该变量是外部链接变量(即引用外部变量),用此标识符不会为变量额外开辟内存(如果使用在另一个文件定义的变量,则必须加上extern标识符)
exit() exit()函数用于结束当前程序 exit(EXIT_SUCCESS);表示程序正常停止 exit(EXIT_FAILURE);表示程序异常停止
指针是一串十六进制数,表示地址,也是一个变量,也有自己的地址。 例:int * d ;int a=1;d =&a ; d的值是a的地址,d指向的值是a的值,&d是d的地址,&d!=&a
在函数中可以定义数组的大小为一个变量(实参)
说明:如果在定义数值型数组时,指定了数组的长度并对之初始化,凡未被“初始化列表”指定初始化的数组元素,系统会自动把它们初始化为0(如果是字符型数组,则初始化为‘\0’,如果是指针型数组,则初始化为
NULL,即空指针)。
二维数组按行存储,a[1][2] 第1行2列 二维数组赋值时可以不指定列数
int a[3][4]={{1},{5},{9}}; //对第1列(即序号为0的列)的元素赋初值.即[0][0]=1, [1][0]=5, [2][0]=9
存储9个字符会占用10个字节(包括\0一个字节),若一个数组存满了字符,则不会有\0结尾
将数组作参数传递时,会改变数组中的值,而变量不会,因为数组是作为指针传递,变量是值传递
对于多维数组,a+1=a[1]=a[1][0] 。 a+2=a[2]=a[2][0]。a[0]+1=a[0][1]
进一步推出*((a+2)+3)=a[2][3] a或a[i]是名字,所以* a和* a[i]是地址
a+2是行号为2的首个元素的地址,*(a+2)也是行号为2的首个元素的地址=&a[2][0]
指针可以赋值为null ,null==0 系统保证地址为0的区域是不存放数据的
一维数组p+6不等于p[6]? 不等于,前一个是地址,后一个是下表6中的数据值 p+0也是地址
二维数组指针p++后p=p[1] *p[1]=p[1][0]
char str[14];//定义字符数组str 在使用字符数组时,声明了就要赋值,否则就应该定义为指针.不能直接将一个字符串赋给字符数组,可以将字符串赋给char指针。
str[]=“I :love China !”;//企图把字符串赋给数组中各元素,错误 str=“I :love China !”//也是错误的
在使用字符指针时,要先给其分配空间,如果不分配空间就直接赋值是错误的
可变格式输出函数:printf(str);相当于printf(“I :love China !”);转义字符也可以
char a[][20] *p=a;则p+20=&a[1][0]? 首先,*p=a这条语句是错的,因为p是char指针,而a是char指针数组。但若能执行,不排除下面说法的正确性(VS中不能执行)
+20相当于指针往后移20个char大小值? 一般+20相当于p[20] *p[20]=p[20][0]
int ( * p)(int, int); //定义p是一个指向函数的指针变量,它可以指向函数的类型为整型且有两个整型参数的函数。p的类型用int( * )(int,int)表示。
c=( *p)(a,b); //通过指针变量调用max函数(使用时用 * p代替函数名即可) c用于接受返回值
赋值只需要p=max即可 //max是函数名
用处:函数指针可以作为另一个函数的参数,使另一个函数能够调用这个函数
int * p[43]; //由于[]比 * 优先级高,所以这是一个元素为指针的数组,常用于元素是字符串时使用
*运算符的结合性是从右到左
将一个结构作为参数传入函数中,在函数内改变结构中变量的值不会影响外面的结构的值。若传递结构指针则会
结构体类型的名字是由一个关键字struct和结构体名组合而成的,例struct student是一个类型
struct student st ; st是一个struct student类型的变量
= struct student {}st; //在声明时创建实体
sizeof运算符测量student 的长度时,得到的不是理论值63,而是64,必然是4的倍数。
struct Student b={.name=“Zhang Fang” }; //对其中一个成员赋值,在成员名前有成员运算符”."
其他未指定的系统初始化,字符初始化\0,指针初始化为null ,其他为0
(5)同类的结构体变量可以互相赋值,如:
student1=student2; //假设student1和student2已定义为同类型的结构体变量
结构体数组
struct student {}st[5]; (*p).name=p->name
typedef 声明新类型名
typedef struct {}st; st是这个结构体的类型名 st student1; //声明一个实例
联合:几中类型共用一个内存,所以共用体变量所占的内存长度等于最长的成员的长度。
在同一时间只能存放其中的一个成员。对其中一个成员赋值相当于对一块地址赋值,相当于对其他所有成员赋值 用处:对同一段数据有不同的用途
枚举:enum Weekday{sun, mon, tue, wed, thu,fri,sat); //enum Weekday为一个枚举类型
可以创建实例:enum Weekday workday; workday是一个枚举类型的实例
workday=mon;相当于workday=1; workday=wed;相当于workday=3;
也可以指定enum Weekday{sun=4, mon, tue, wed, thu,fri,sat); //则mon=5,thu=8
ASCII文件和二进制文件,ASCII文件是按数字个数存储的,即每一个数占一个字节,而二进制文件是按为存储的,即将其转为二进制数存储,例10000ASCII占5个字节,40位,二进制占2个字节(16位)
FILE其实是一个结构体类型,可以创建实例FILE * fp; //指向文件的指针变量。
fopen函数的返回值是指向文件的指针(即文件信息区的起始地址)。通常将fopen函数的返回值赋给一个指向文件的指针变量。
在正式编译前会有预处理,预处理阶段将注释全部清除,并对预处理指令进行处理
宏定义:一般用宏代替简短的表达式
#define 标识符 字符串 //即用标识符表示这个字符串,
#define定义的常量和函数本质是做代码的转换 ,例:#define f(x) xm #define m n+1 则f(1+1)=1+1n+1=n+2 (x表示字符串1+1 m表示字符串n+1 所以f(x)表示字符串1+1n+1)
2. #define char byte 则可以用byte代替char声名变量,但一次只能声名一个
3. #define sout(x) printf(“this is”#x"or is %d",x+x) sout(3+2); 则输出 this is 3+2 or is 10 即"#x"输出为传入的参数,如果参数是yy,则"#x"为y*y
4. #define sout(x) printf(“this is”#x"or is %d",s##x) sout(3);则输出 this is 3 or is is s3
5. 变参宏 … 表示多个参数,对应_ VA_ARGS _
例:#define ct(x,…) pfintf(“sd”#x"d"_ VA_ARGS _); ct(1,“a=%d,b=%d”,a,b); 输出 sd 1 da= a ,b= b
文件预处理:#include
可以用#include
进行编译时则预处理(执行)a.c中的所有代码
条件编译 可以用于main函数中
#ifdef mc //如果已经用#define定义了mc则执行下面的代码。#ifndef :如果mc未定义过则执行下面的代码,其他用法不变
#define cc 20
#else 否则执行下面的代码
#define bb 20
#endif //if结束
—#if和#elif #if后面可以用常量不等式例:#if mc ==20 #elif和else一样,语句依然用 #endif结束
#if 后面的表达式值为非0,则往下执行
其他指令
—#undef 用于终止宏定义的作用域,即宏定义的标识符的使用范围到#undef结束
例:#define mc 200 #undef mc 则mc相当于没用定义过
/012 表示八进制数12的十进制数表示的ASCII码(即为ASCII码为10的字符—换行符)
/x41为十六进制=A
数字 3.2表示最少输出3个字节且输出小数点后2位
”-“ 左对齐打印,从左侧开始打印 如%-4d(假如待打印的int值为3) 则输出结果为3 (后面有三个空格)
”+“ 取反 如%+d(假如待打印的int值为3)则输出结果为-3
如何实现回溯,即在无路可走的时候回到上一个交叉路口,书129页
典型错误:if后的语句和else后的语句一次循环只会有一个被执行
在do块内执行break会结束循环,
Switch循环过程不会经过循环头,即不会再执行循环判断语句,第一次循环后直接进入case语句
char a=‘4’;char b=‘2’;则a-b=2
if(x–<1) y++;相当于if(x<1) x–{y++;} //即若x=2时,执行上面语句,x=1
逻辑与在左表达式为0时不会执行右表达式 逻辑或在左表达式为真时不执行右表达式