C语言学习笔记

来源:互联网 发布:东控门禁软件 编辑:程序博客网 时间:2024/04/30 12:36

C语言学习笔记

第一章 C语言概述

1.运行c程序的步骤

   上机输入与编写源程序->对源程序进行编译(目标程序object program)->与库函数连接->执行目标程序。整个步骤的说明:编辑程序保存得到一个源程文件program.c,然后在进行编译时再将源程序文件program.c输入,经过编译得到的目标程序文件program.obj,再将其目标文件program.obj输入内存与系统提供的库函数等连接,得到可执行的目标程序program.exe,最后把program.exe调入内存并使之运行。为了编译,连接和运行c程序,必须要有相应的c编译系统,目前使用的大多数c编译系统都是集成环境(IDE)的,把程序的编辑,编译,连接和运行等操作全部集中在一个界面上进行,功能丰富,使用方便,直观易用。编译系统(Turbo C2.0 Turbo C++3.0 Visual C++).由于C++是从C语言发展起来的,所以C程序可以在C++集成环境中进行编译,调试和运行。

第三章 数据类型,运算符和表达式

1数据类型,运算符和表达式

1.1在一般的编译系统中Int 类型的数据为其分配2个字节(16),但是Visual C++6.0为整型分配4个字节(32)Short--2Bit Int--4Bit

1.2Turbo 系列的编译系统中,一个int型的变量的最大值允许为32767,如果加1,将会出现益处现象。说明:在计算机内int数据的存储格式都是以它的补码形式存放的,32767最高位是0(正数),其余15位都是1,加上1后变成第一位是1,其余15位是0,而它是-32768的补码形式,将其通过反码转换成源码就是-32768

1.3 一个整型常量后面加上一个字母u或者U,认为是unsigned int型,如12345u在内存中是按unsigned int规定的方式来存放的(存储单元中最高位不作符号位,而用来存储数据)。如果写成-12345u,则先将-12345转换成其补码,然后按无符号数存储。

1.4 一个浮点型数据一般在内存中占4Bit(32bit),与整形数据的存储方式不同,浮点型数据时按照指数形式存储的。系统吧一个浮点数据分成小数部分和指数部分。

1.5 字符型变量用来存放字符常量,只能放一个字符,将一个字符常量放到一个字符变量中,实际上并不是把该字符本身存放到内存中,而是将该字符相应的ASCII 代码存放到存储单元中。说明:字符'a'ASCII码是十进制97,但是在内存中是97的二进制存放的。所以intchar之间可以通用,进行算术运算。

1.6 'a'"a"的区别。C规定:在每一个字符串常量的结尾加一个"字符串结束标记"('/0'),以便系统判断字符串是否结束。'/0'是一个ASCII码为0的字符,是"空操作符",即它不引起任何控制动作,也不是一个可显字符。"a"包含a'/0',包含两个字节,因此不能用char字符变量来存储,可用char型数据来存储。

1.7 变量赋初值 int a=3,b=3,c=3; 不能写成 int a = b = c = 3; 说明:初始化不是在编译阶段完成的(静态存储变量和外部存储变量的初始化是在编译阶段完成的),而是在程序运行时执行本函数时赋初值的,相当于 int a,b,c; c=3;.

1.8 各类数值型数据间的混合运算  字符数据必定先转换成整数,short 转换为intfloat在运算时一律先转换为双精度(double),然后再相加。不同类型转换:intdouble间进行运算,先将int型转换成double,再相加。Int(char,short)->unsigned->long->double(float)

1.9 强制类型转换运算符  可以利用强制类型转换运算符将一个表达式转换成所需类型。(double)a  (int)(x+y)   (float)(5%3)(int)x+y:x转换成int整型再与y相加。说明:在强制类型转换时,得到一个所需类型的中间变量,原来变量的类型未发生变化。有两种类型转换:一种是在运算时不必用户指定,系统自动进行的类型转换,如3+5.4.第二种是强制类型转换,当自动类型转换不能实现目的时,可以用强制类型转换,如"%"运算符要求其两侧均为整型,若xfloat,则"x%3"不合法,必须用"(int)x%3".因为强制类型转换运算优先于'%',因此先进行(int)x的运算,得到一个整型的中间变量,然后再对3求模。

1.10  自曾运算符(++)和自减运算符(--)只能用于变量,而不能用于常量和表达式。如5++(a+b)++都是不合法的,因为5是常量,常量的值是不能改变的;若a+b的值为5,那么自增后得到的6存放在什么地方,无变量可存放。-i++ == -(i++) i+++j == (i++)+j。多数系统中,在调用函数时,是参数的求值顺序:自右向左。例子:printf("%d,%d",i.i++);先求i++,再求i。所以避免让别人难以看明白,可以这样写 j=i++;printf("%d %d",i,j);

1.11  逗号运算符  其求解过程:先求表达式一,再求表达式二,整个表达式的值是表达式二的值。例子:a=(3*5,a*4),a+5;计算过程:先计算出a的值是3*5=15,再进行a*4=60(a值没有变化,仍为15),再a+5=20,所以整个表达式的值为20(x=a=3,6*3),其包括一个赋值表达式和一个算术表达式,x的值是3,整个表达式的值是18

第四章 最简单的C程序设计--顺序程序设计

赋值语句  C语言中的赋值号"="是一个运算符,在其他大多数语言中赋值号不是运算符

数据输入输出的概念及在C语言中的实现

  C语言本身不提供输入输出语句,输入输出操作是C函数库中的函数来实现的。在C标准函数库中提供了一些输入输出函数,例如printfscanf,不要误认为他们是C语言中提供的"输入输出语句"printfscanf不是C语言的关键字,而是函数的名字。C提供的函数是以库的形式存放在系统中,他们不是C语言文本中的组成部分。不把输入输出作为C语句的目的是使C语言编译系统简单,因为将语句翻译成二进制的指令是在编译阶段完成的,没有输入输出语句就可以避免在编译阶段与硬件相关的问题,可以使编译系统简化,而且通用性强,可移植性好,在各种型号的计算机厂商(或软件公司)根据用户的需要编写的,并且已编译成目标文件(.obj).他们在连接阶段与由源程序经编译而得到的目标文件相连接,生成一个可执行的目标文件(.exe)。如果在源程序中有printf函数,在编译时并不是把他翻译成目标指令,在连接阶段与系统函数库相连接后,在执行阶段中调用函数库中的printf函数。加入函数库#include <stdio.h>

第五章  选择结构程序设计

1.关系表达式的值是一个逻辑值,即""""C语言没有逻辑型数据(C++有逻辑型变量和逻辑性常量,以TrueFalse)。在C的逻辑运算中,以"1""0"分别表示真,假。字符型,实型或者指针型,系统以0和非0来判断,他们ASCII不为0,则为非0,即为真。

2.条件运算符 例子:x>y?1:1.5;如果x<=y,则值为1.5,x>y,值应为1,由于1.5是实型,比整型的优先级高,将1转换成实型值1.0。则值应为1.0

第七章 数组

1.C语言规定只能逐个引用数组元素而不能一次引用整个数组。数组下标可以是整数常量和整型表达式。A[2*3];

2.一维数组的初始化。Int a[10]={1,2,3,4,5,6,7,7,8,9};,可以只给一部分元素赋值,如果全部元素都一样可以a[10]={0};在确定元素个数时可以不指定其长度。

3.二维数组的初始化。Int a[2][3]={{1,2,3},{3,4,5}};可以将所有数据写在一个花括号内,安数组排列的顺序对各元素赋值。

4.字符数组与字符串常量。在C语言中,是将字符串作为字符数组来处理的。但在数组中'/0'只能认为加上,如果要有效的利用字符数组,最好与字符串常量在内存中的存放保持一致,即在数组最后加上一个'/0'来判断字符串的结束。例如:char c[]="cccc program";若想用一个新的字符串代替原有的字符串"cccc program",从键盘响字符数组中键入chen,如果不加'/0',则输出的是 "chen program".

第八章 函数

1.函数类型为void,意为函数无类型,即无函数值,执行这个函数后不会把任何值带回main函数。

2.C语言中,实参向形参的数据传递的是"值传递",单项传递,只由实参传给形参,而不能有形参传回来给实参。在内存中,实参单元与形参但与是不同的存储单元。在调用函数时,才给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。因此,在执行一个被调函数时,形参的值如果发生改变,并不会改变主调函数的实参的值。

3.C语言中,若不加函数类型说明的函数,系统将自动按整型处理。

4.许多系统,安自右到左的顺序求值的。如:p=f(i,++i);那么第二个参数将先执行,i若为2,参加运算(++i)后为3,则第一个参数为3

5.函数的声明"declaration".作用:是把函数名,函数参数个数,参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确识别函数并检查调用是否合法。如果已在文件的开头(在所有函数以前),已对本文件中所调用的函数进行了声明,则在各函数中不必对其所有调用的函数再做声明。

6.数组名也可以用作实参和形参,传递的是数组的首地址。类似与指针,因此形参数组中的各元素发生变化会使实参数组元素同时发生变化;数组元素做函数实参与变量作实参一样,是单向传递,即"值传递"

7.二维数组做实参和形参,并需指定列数(一行中包含几个元素)。因为:在内存中,数组是按照行存放的,只要确定了列数,实参和形参的元素才能对号入座。如:a[][4]; f(b[][4]);

8.全局变量在不是很必要时不要使用,原因:㈠全局变量在程序的全部执行中都占用存储单元,而不是仅在需要时才开辟单元;㈡它使函数的通用性降低,因为函数在执行时需要依赖于其所在的外部变量;㈢使用过多会降低程序的清晰性;㈣如果在同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量被"屏蔽",即它不起作用。

9.变量的存储类别  从变量值存在的时间来分,可以分为静态存储方式(在程序运行期间由系统分配固定的存储空间)和动态存储方式(根据需要进行动态的分配存储空间)。内存中提供给用户的存储空间分为三部分:1.程序区;2.静态存储区3.动态存储区。数据分别存放在静态和动态存储区中。全局变量全部存放在静态存储区中,在程序开始执行时给全局变量分配存储区,程序执行完毕就释放。在程序执行过程中他们占固定的存储单元,而不是动态进行分配和释放。动态存储区存放以下数据:1.函数形式参数,在调用函数时给参数分配存储空间2.自动变量(没加static声明的局部变量)3.函数调用时的现场保护和返回地址等。以上这些数据,在函数调用开始时分配动态存储空间,函数结束时释放空间。在程序执行过程中,这些分配和释放都是动态的,如果在一个程序中两次调用统一函数,分配给此函数中局部变量的存储空间地址可能是不相同的。如果一个程序包含若干个函数,每个函数中的局部变量的生存周期并不等于整个程序的执行周期,只是程序执行周期的一部分。

10.Auto变量 函数中的局部变量,如果不专门声明为static存储类型,都是动态地分配存储空间。在函数调用时会自动分配空间,函数调用结束时会自动释放空间,这类局部变量称为自动变量 auto int a = 3 == int a =3;

11.Static声明局部变量 函数中的局部变量的值在函数调用结束后不消失而保留原值,其占用的存储单元不释放,在下一次该函数调用时,该变量已有值,就是上一次函数调用结束时的值。说明:1静态局部变量属于静态存储类型,在程序整个运行期间都不释放。2对静态局部变量时在编译是赋初始值,即只赋初值一次,在程序运行时他已有初值。在定义局部变量不赋值的话,对静态局部变量而言,编译时自动赋值0(对数值)或空字符(对字符)。而对自动变量来说,不赋值则它的值是一个不确定的值,这是由于每一次函数调用结束后存储单元也释放,下次调用时有重新另分配存储单元,其值是不确定的。4在函数结束时仍然存在,但其他函数无法引用它。

12.Static 声明外部变量 该外部变量只能在本文件中被使用,其他文件不能访问。File.c static int a; file2.c extern int a; file2.c中不能访问file.c中的a变量。

static来声明一个变量作用有二:①对局部,则使该变量在整个程序执行期间不释放,为其分配的空间始终存在②对全局,作用域只限于本文件模块(即被声明的文件中)

13.register变量 将变量存放在cpu的寄存器中,加快数据访问。通常用于较高的循环。但不是很常用。  变量的执行过程:程序中用到的变量时,由控制器发出指令将内存中该变量的值送到运算器中,经过运算器运算,如果需要存储,将值从运算器到内存中。

14.Extern声明外部变量  如果外部变量不在文件的开头定义,其有效作用域只限于定义处到文件借书处。Extern int a 在文件的任何地方定义,a的范围都是整个文件。

15.Extern在多个文件中定义  file1.c auto int a;file2.c extern int a;能访问file1.c中的a

16.内部函数 static int fun1();只能在本文件中访问extern int fun2();访问的是另外文件中的函数。

第九章 预处理命令

ANSI C标准规定可以在C源程序中加入一些"预处理命令(preprocessor directives)",以改进程序设计环境,提高编程效率。这些预处理命令是有ANSI C统一规定,但不是C语言的组成部分,不能直接对他们进行编译(编译程序不能直接识别它们)。必须对程序进行通常的编译(包含词法和语法分析,代码生成,优化等)之前,先对程序中这些命令进行预处理。预处理之后的程序不再包括预处理命令了,最后再有编译程序对预处理后的源程序进行通常的编译处理,得到可执行的目标代码。

1.宏定义 #define PI 3.1415926  #define S(a,b) a*b

2.文件包含 #include <stdio.h> 系统自带文件  #include "myfile.h" 用户自定义文件

3.条件编译 

#ifdef(ifndef) 标示符 (if  表达式)  ifdef 如果定义 程序1ifndef 如果为定义 程序段1

程序段1

#else

程序段2

#endif

第十章  指针

1.通过指针引用数组元素 如果p的初始值为&a[0],则⑴p+ia+i就是a[i]的地址,他们指向a数组的第i个元素。⑵*(p+i)*(a+i)p+ia+i所指向的数组元素⑶指向数组的指针变量也可以带下标,如p[i]==*(p+i).

2.多维数组与指针  从二维数组的角度来看,a代表二维数组首元素的地址,现在的首元素不是一个简单的整型元素,而是由n个元素所组成的一维数组,因此a代表的是首行的首地址。a+1代表第一行的首地址。a[0]==*(a+0),a[1]==*(a+1),a[0]+1==*(a+0)+1==&a[0][1];

3.C语言对字符串常量是按字符数组处理的,在内存中开辟一个字符数组来存放该字符串常量。对字符串指针变量string初始化,实际上时把字符串第一个元素的地址赋给stringPrintf("%s/n",string);%s输出字符串时所用的格式符,在输出项中给出字符指针变量名string,则系统先输出它所指向的一个字符数据,然后自动使string1,使之指向下一个字符,然后再输出它所指向的一个字符,直到遇到结束标记'/0'为止。注意:在内存中,字符串的最后被自动加了一个'/0'

4.Char *a; scanf("%s",a);虽然能运行,但是很容易出错。因为:编译时会给指针分配内存单元,但a的值为被指定,只是指向了任意的一个内存单元,scanf欲将键盘输入的值赋值给a所指向的地址,但是对一个任意的地址,scanf无法指向。应先使a指向一个数组的首地址,然后输入一个字符串,把它存放在以该地址开始的若干单元中。

5.数组名虽然代码地址,但是它是常量,它的值是不能改变的。Char str[]="i love china";str=str+9;error!!!

6.用函数指针调用函数  一个函数在编译时被分配一个入口地址,这个函数的入口地址就称为函数的指针。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。例子:

#include<stdio.h>

Void main()

{

Int max(int,int);

Int (*p)(int,int);//p来定义指向函数的指针变量 形式:数据类型 (*指针变量)(函数参数表列)

Int a,b,c;

P=max;//max函数的入口地址赋值给p指针变量

Scanf("%d,%d",&a,&b);

C=(*p)(a,b);//调用函数

Printf("a=%d b=%d,max = %d",a,b,max);

}

Int max(int x,int y){...}

7.指向函数的指针做函数参数  用指向函数的指针作为参数,以实现函数地址的传递;用于函数在调用不固定函数时作用比较大。例子:

Void sub(int (*x1)(int), int (*x2)(int,int))

{

   Int a,b,i,j; 

   a=(*x1)(i);

   b=(*x2)(i,j);......

}

8.返回指针值的函数  int *a(int x,int y);a是函数名,调用它以后能得到一个指向整型数据的指针。例子:有若干个学生的成绩,要求在用户输入学生序号以后,能输出该学生的全部成绩。

#include<stdio.h>

Void main

{

Float score[][4]="...";

Float *search(float (*pointer)[4],int n);

Float *p;

Int i,m;

Printf("enter the number of student");

Scanf("%d",&m);

Printf("the score of NO.%d arevage is :/n",m);

P=search(score,m);//得到返回的score的行数首地址

For(i=0;i<4;i++)

Printf("%5.2f/t",*(p+i));

    Printf("/n");

}

Float *search(float (* pointer)[4],int n)

{

Float *pt;

Pt=*(pointer+n);

Return(pt);

}

9.指针数组  int *p[4];定义一个数组,里面有4个元素,每个元素存放的是地址。不能写成int (*p)[4];它是指向一维数组的指针变量,等价于 int a[][4](二维数组);p++,指向第一行的首地址。

10.指针数组做main函数的形参   void main(argc,*argv[]);参数可以写成一下形式,file1,china,beijing.实际上,文件名应包括盘符,路径以及文件的扩展名。Argc是命令行中参数的个数,这个就是3Agrv[]是存储每个参数的首地址。利用指针数组做main函数的形参,可以向程序传送命令行参数。

11.有关指针的数据类型和指针运算的小结

Int i;      定义整型变量

Int *p;     p为指向整型数据的指针变量

Int a[n];    定义整型数组a,它有n个元素

Int *p[n];   定义指针数组p,它有n个指向整型数据的指针元素组成

Int (*p)[n];  p为指向含n个元素的一维数组的指针变量

Int f();     f为返回整型函数值的函数

Int *p();    p为返回一个指针的函数,该指针指向整型数据

Int (*p)();   p为指向函数的指针,该函数返回一个整型值

Int **p;    p是一个指针变量,它指向一个指向整型数据的指针变量

12.void指针类型  用来指向一个抽象的类型的数据,在将它的值赋给另一个指针变量时要进行强制类型转换是指适合于被赋值的变量的类型。

第十一章  结构体和共用体

 

第十二章 位运算

第十三章 文件

C语言把文件看作是一个字符(字节)的序列,即由一个一个字符(字节)的数据顺序组成。根据数据的组织形式,可分为ASCII文件和二进制文件。ASCII文件又称为文本(text)文件,它的每一个字节放一个ASCII代码,代表一个字符。二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。如果有一个整数10000,在内存中占2个字节,如果按ASCII码形式输出,则占5个字节,而按二进制形式输出,在磁盘上只占2个字节。

第十四章 常见错误和程序调试

原创粉丝点击