C语言摘要
目 录
C语言摘要... 1
目 录... 1
第一章 C的数据类型和常量... 2
1.基本类型... 2
2.构造类型... 2
3.指针类型... 4
4.空类型... 4
5.常量... 4
第二章 标识符约定... 4
第三章 变量... 4
1. SizeOf4
2. 局部变量 5
3. 全局变量 5
4. 静态存储和动态存储 5
5. 总结 5
第四章 C的运算符和表达式... 6
第五章 控制语句... 6
第六章 函数... 6
第七章 编译预处理... 7
第八章 指针... 8
1.什么是指针... 8
2.变量的指针和指向变量的指针变量... 9
3.数组的指针和指向数组的指针变量... 9
4.字符串指针和指向字符串的指针变量... 9
5.函数的指针和指向函数的指针变量... 9
6.指针数组和指向指针的指针... 9
7.结构体变量或数组的指针和指向它们的指针变量... 10
第九章 文件... 10
1.文件类型指针... 10
2.文件的打开... 10
2.文件的关闭... 10
3.文件的读写... 11
4.文件的定位... 11
5.出错的检测... 11
第一章 C的数据类型和常量
1.基本类型
(1)整型
整型通常包括 int / short int / long int / unsigned int / unsigned short / unsigned long
关于Size的说明:每个不同的机器和操作系统对这些数据类型分配的地址大小是不同的,以通用的Windows的32系统来说,一般给
int
的是
4 bytes ,给short 的是 2 btyes,给long的是4 bytes。
(2)字符型
关于Size的说明:通常char类型都是占用1byte的内存空间,但在C#中,char类型通常是占用2bytes的内存空间的,因为在C#中,使用的Unicode字符集。
(3)实型
实型包括 float 和 double 类型
关于Size的说明:通用的Windows的32系统来说,一般给
float
的是
4 bytes
,
double
的是
8bytes
。
(4)枚举类型
在C中,枚举元素是按常量处理,它们不是变量,不能对它们赋值;
C在编译时,按定义时的顺序使枚举元素的值为0,1,2,……;
程序员也可以自己指定枚举元素的值。
EG:
enum weekday {sun,mon,tue,wed,thu,fri.sat};
(5)用typedef定义类型
typedef struct
{int year,month,day;}DATE;
使用: DATE birthday;
如果使用 struct DATE
{int year,month,day};
使用: struct DATE birthday;
2.构造类型
(1) 数组
1.1
数组的定义
类型说明符 数组名[常量表达式1] [常量表达式2] [常量表达式…]
1.2 数组的初始化
(1) 在定义数组时对数组元素赋初值,但是要注意
只有静态存储数组和外部数组才能初始化
;
同时
,
在初始化的时候
,
可以只对一部分数组赋值
;
EG:
static int a[10]={0,1,2,3,4,5};
(2) 在对全部数组赋初值时,可以不指定数组长度;
1.3
数组元素的使用
1.4 使用数组或数组元素传递参数
1.6 字符串和字符串结束标志’/0’
1.7 字符串处理函数
(1)
puts(str)
(2)
gets(str)
(3)
strcat(str1,str2)
注意
:str1
要足够大以容纳新字符串
,
下同
(4)
strcpy(str1,str2)
strcpy(str1,str2,拷贝的字符数) 自动加’/0’
(5)
strcmp(str1,str2)
(6)
strlen(str)
(7)
strlwr(str)
(8)
strupt(str)
(2) 结构体
2.1 定义
struct 结构体名
{成员列表;}变量名0,变量名1,…变量名n
;
EG:
struct student
{int num;
char name[20];
};
技巧
:
为了方便
,
通常使用一个符号常量代表一个结构体类型
,
如
#define STUDENT struct student
STUDENT
{int num;
char name[20];
};
2.2 结构体类型变量的引用 结构体变量名
.
成员名
(1)
不能将一个结构体变量作为一个整体进行输入/输出;
(2)
如果成员本身又是一个结构体类型,则要一级一级地找到最低一级的成员。换句话来说,就是一定要找到最底层的存放数据的空间;
(3)
成员变量可以和一个普通变量一样使用;
(4)
可以引用成员的地址,也可以引用结构体变量的地址
EG:
scanf(“%d”,&student1.num);
printf(“%o”,&student1); //输出student1的地址
结构体变量的地址主要用于作函数参数,传递结构体的地址;
2.3
初始化
2.4
结构体数组
(3)共用体类型 不常用
3.指针类型
指针是C语言使用最为灵活和重要的部分,下面会详细展开;
关于Size的说明:以32为系统来说,Point类型通常都会占用 4 bytes的内存空间的。这是因为32位操作系统的内存寻址空间是2的32次方,所以想表达这么多的空间,必须需要32bits的空间,也就是 4bytes。
4.空类型
5.常量
C语言中,常量有常量和符号常量两种;
EG: 常量 123,1.03,‘a‘
符号常量 #define PRICE 30
第二章 标识符约定
1.数字、字母、下划线是有效字符,但是只能以字母开头;
2.大小写敏感;
3.注意各编译器或系统对标识符的长度约束;
第三章 变量
考察变量要从以下几个方面:变量名、变量值、变量类型、变量的作用域、变量的存储类别、变量的内存地址、变量的存储空间、变量的存储区域等。
1.SizeOf
EG:以下为
Windows NT 下的
32 位
C++程序,请计算
sizeof 的值
void Func ( char str[100])
{请计算
sizeof( str ) =
4
;
}
char str[] = “Hello” ;
char *p = str ;
int n = 10
;
请计算
sizeof (str ) = 6
sizeof ( p ) =
4
sizeof ( n ) =
4
void *p = malloc( 100 );
请计算
sizeof ( p ) =
4
2.局部变量
在函数内部定义的变量
3.全局变量
在函数外定义的变量,使用时,可能需要添加 extern 关键字来说明该变量是来自外部的。
注意:使用全局变量的优缺点:
(1)
优点
增加了函数间数据联系的渠道
减少函数实参与形参的个数,从而减少内存空间以及传递参数时的时间消耗;
(2)
缺点
在程序的所有执行期间都一直占着内存空间;
降低了函数的通用性和可靠性,以及降低程序的可读性;
4.静态存储和动态存储
静态存储:在程序运行期间分配固定的存储空间的方式
动态存储:在运行期间根据需要进行动态分配存储空间的方式
用户区: 程序区 + 静态存储区 + 动态存储区
5.总结
局部变量: 自动变量auto、静态局部变量、寄存器变量register、形参
全局变量: 静态外部变量(只限本文件引用static)、外部变量(还允许其他文件引用)
动态存储: 自动变量、寄存器变量、形参
静态存储: 静态局部变量、静态外部变量、外部变量
?静态局部变量和其它局部变量区别:静态局部变量在离开函数,它的值依然保留
第四章 C的运算符和表达式
1.关系运算符
> < == >= <= !=
2.逻辑运算符
&& || !
3.条件运算符号
(…)?(…),(…)
4.表达式
算术表达式、赋值表达式、逗号表达式、关系表达式、逻辑表达式
第五章 控制语句
1.条件控制
if (…) else ~
switch ()
{
case … : break;
case … : break;
case … :
break;
.
.
.
defaule : ….
}
2.循环控制
for(…,…,…)
do … while ()
while() {}
3.其他
continue
goto
return
第六章 函数
1. 函数的定义
类型标识符 函数名(形参列表){函数体}
2.函数的参数及其传送方式:传值,传地址
3.函数的返回值
4.函数的调用方式
5.函数的嵌套调用
6.函数的递归调用
7.内部函数:如果一个函数只能被本文件的其他函数引用,它称为内部函数,加static
8.外部函数:extern 隐含的~
注意:在需要调用某外部函数时,和使用外部变量一样,一般需要加以
extern
关键字说明这个函数是从外部调用的。
第七章 编译预处理
1. 宏定义
#define 宏名(参数表) 字符串
本质:替换字符串
EG:#define PI 3.1415926
#define ARRAY_SIZE 100
宏不存在什么类型的概念,本质上就是起到 替换字符串 的作用。但是使用宏有很重要的意义:
(1)
提高了程序的可移植性
(2)
方便了编程
但是由于宏本身不作任何的语法检查,所以在使用时要特别注意,如:
#define S(a) a*a
main()
{float a,area;
a=3.6;
area=S(a);
à area=a*a
}//这可以工作!
main1()
{float a,b,area;
a=3.6;b=4.0;
area=S(a+b);
à area=a+b*a+b
}//这就有问题
为了解决这个问题,我们可以在定义宏的时候使用()来保证:#define S(a)=(a)*(a)
宏的作用域:整个文件,但是我们也可以使用#undef来取消我们定义的某个宏
?注意:宏的替换过程是在编译的过程中完成的~
2. 文件包含处理
#include
作用就略去了!!!
例子:#include 和 #include “filename.h” 有什么区别?
答:对于
#include ,编译器从标准库路径开始搜索
filename.h
对于
#include “filename.h” ,编译器从用户的工作路径开始搜索
filename.h
如果我们不清楚filename.h在什么路径,可以使用
#include “filename.h”
这样的命令,可以确保能够找到,当然,如果我们明确知道该文件不在我们的工作路径中,当然应该使用
#include
来节省查找文件的时间。
3. 条件编译:(提高可移植性、灵活性和方便调试)
指令1: #ifdef 标识符
程序代码段1
#else
程序代码段 2
#endif
用途:如果定义了标识符,则执行1,否则执行2
指令2:#if
ndef 标识符
程序代码段1
#else
程序代码段 2
#endif
用途:如果定义了标识符,则执行2,否则执行1
指令3:#ifdef 表达式
程序代码段1
#else
程序代码段 2
#endif
用途:如果表达式非零,则执行1,否则执行2
问题:带参数的宏和函数有哪些区别?
答:(1)从二者的定义上来看,函数是完成某一个特定功能的,返回值具有数据类型的,但是宏在定义的时候就不存在类型的问题;
(2)从调用上看,函数调用是在程序运行时处理的,其参数也是在程序运行时临时分配的存储单元,参数的值是由调用函数传送过来。而宏是在程序编译时处理的,仅仅是替换了字符串,不存在值的传递过程;
(3)从运行结果来看,函数调用都有一个返回类型,即使是void的返回值也好。但是宏运行完以后,不存在什么类型的问题;
(4)调用函数只能返回一个值,而用宏可以设法得到几个结果。
(5)使用宏次数多时,宏展开后源程序长,而函数调用不使源程序变长;
(6)宏替换不占运行时间,只占编译时间,而函数调用占用运行时间。
第八章 指针
1.什么是指针
指针:内存单元的地址
指针变量:记录地址的内存单元
?使用指针的优点:
l
能够有效表达复杂的数据结构;
l
能动态分配内存;
l
能方便使用字符串;
l
有效方便的使用数组;
l
在调用函数时能够得到多于
1
个的值,当然,也可以使用数组和结构体来达到这个目标;
l
能直接处理内存,这对于设计系统软件、驱动开发是十分重要的。
2.变量的指针和指向变量的指针变量
定义: 类型标识符 *指针变量名
int *pointer_1;
如果想通过函数调用得到n个要改变的值,就可以:在主调函数中设置n个变量,用n个指针变量指向它们;
3.数组的指针和指向数组的指针变量
定义: 类型标识符 *指针变量名
int *pointer_1;
int a[10];
pointer_1=&a[0] ;
或 pointer_1=a;
4.字符串指针和指向字符串的指针变量
char *string=”I love China!”;
5.函数的指针和指向函数的指针变量
一个函数在编译时被分配了一个入口地址,这个入口地址就称为函数指针;
定义:如
int (*p) ();
int max(); //max
是定义在本文件的函数
p=max;
调用:
(1)
函数名
(2)
指针
(*p)();
注意:函数指针,在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。在一个程序中,该指针可以先后指向不同的函数;
赋值直接使用
p
=
max
之类的就可以;
对指向函数的指针进行
p
++,
p
+
n
等操作都是无意义的;
??返回指针值的函数:定义
int *a(x,y);
6.指针数组和指向指针的指针
指针数组 类型说明符
*数组名[常量表达式1] [常量表达式2] [常量表达式…]
指向指针的指针 类型说明符
**
变量名
7.结构体变量或数组的指针和指向它们的指针变量
注意
:
int *p[n]; :
定义指针数组
,
它有
n
个指向
int
数据的指针组成
;
int *p(); p
为带回一个指针的函数
;
int (*p)(); p
为指向函数的指针
,
该函数返回一个
int
类型的数据
;
int **p p
为一个指针变量
,
它指向一个指向
int
类型指针变量所在的内存单元
;
动态分配内存的函数
:
malloc(size);
在内存的动态存储区中分配一个长度为
size
的连续空间
,
并返回的这个地址的首地址
;
如
: int p; p=(int *)malloc(sizeof(int)); // (int *)
是转换指针类型的作用
calloc(n,size):
在内存的动态存储区中分配
n
个长度为
size
的连续空间
,
并返回的这个地址的首地址
;
free(ptr) :
释放由
ptr
指向的内存区域
relloc(size)
第九章 文件
1.文件类型指针
一般C语言的版本在stadio.h文件中有定义FILE的结构;
2.文件的打开
FILE *fp;
fp=fopen(文件名,使用文件方式) fp=fopen(“a1”,”r”);
r w a rb
wb ab r+ w+ a+ rb+ wb+ ab+
常打开一个文件的代码:
if ((fp=fopen(“filename”,”r”))==NULL)
{ printf(“cannot open this file.”);
exit(0);
}
2.文件的关闭
fclose(fp);
如果返回值是0,说明关闭成功;反之,说明在关闭时有错误,可以使用ferror来测试。
3.文件的读写
(1)
fputc(ch,fp)
(2)
char c=fgetc(fp);
(3)
fread(buffer,size,count,fp);
(4)
fwrite(buffer,size,count,fp);
4.文件的定位
(1) rewind (fp); 使位置指针重新返回文件得开头;
(2) fseek (fp,位移量,起始点0 1 2) 改变fp的位置指针;
5.出错的检测
(1) ferror(fp);
注意:打开一个fp后,ferror的值赋为0,然后每对改文件调用一次读写函数,均产生一个新的ferror值,因此,应当在调用一个读写函数后立即检查ferror的值。
上述的都是指的是缓冲文件系统,也有一些用于非缓冲文件系统的函数,这里就省略了~。