C语言的数据类型
基本数据类型有:整形(short int、int、long int),实型(float、double、long double),字符型char。
构造类型有:数组、结构体struct、枚举型enum、共用体union。
注:数组说白了就是一个容器;枚举就是为了限定数据选择
二、规定不同的数据类型是为了计算机内部方便作数据处理,占多大内存空间
三、常量与变量
1、常量:值不可改变的数据对象。
(1)整形常量
普通字符常量:用单引号扣起来
转移字符常量:一对单引号扣起来并以"\"开头的字符序列。如'\n'
(4)字符串常量:使用(" ")括起来的字符序列
注:注意字符常量是(' ')。长度位n的字符串在计算机中存储占n+1个字节,最后一位存的是NULL,在c中也用\n表示。
(5)符号常量
定义有两种方法:const int AGE=100;
引入符号常量有两个好处:
补充:#define和const 的区别
第一点:#define常量在程序变异预处理的时候就万封不动的替换了,在运行时并不实际存在;const常量在程序执行阶段仍有效;
第二点:#define常量运行时已经不存常量,因此不会为其分配内存;const常量实际上定义了一个其值不能修改的变量定,因此在堆栈上为其分配了空间;
第三点:#define常量替换后被编译进程序文件的代码段,const常量存在程序文件的数据段。
2、变量:相对于可以赋值
定义形式:
变量的数据类型转换:隐式转换(自动转换)
(1)自动转换:发生在不同数据类型的量混合运算时,由编译器系统自动完成。
注:第一:所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算。
(2)强制转换
形式为
四、运算符和表达式
1、运算符
优先级总结:初等运算符()[ ] ->
自增、自减运算符分析
++i
--i
i++
i--
2、表达式
算术表达式 注:%取余 要求参与运算的都是整数
赋值表达式
复合赋值表达式
自加表达式
逗号表达式 优先级最低,表达式的数值是最右边那个表达式的数值 如(2,3,4)的表达式的值就是4
分支、循环
1、判断:if、switch
if三种形式:第一、if(表达式)语句
注:if语句可以嵌套
switchi只支持整数相等判断
2、循环控制:for 、while、do while
(1)for(表达式1,表达式2,表达式3)
(2)while与do while 主要区别是后者先执行在判断,因此至少执行一次。
(3)break表示终止循环
二、本章涉及到的函数
1.scanf 函数
其调用格式为: scanf("格式化字符串",地址表);
scanf("%d,%d", &a, &b);
如果a和b都被成功读入,那么scanf的返回值就是2
如果只有a被成功读入,返回值为1
如果a和b都未被成功读入,返回值为0
如果遇到错误或遇到end of file,返回值为EOF。
且返回值为int型.
注:对于字符串数组或字符串指针变量,由于数组名和指针变量名本身就是地址,因此使用scanf()函数时,不需要在它们前面加上"&"操作符。
%d
%c
%lf
%x
2、printf函数
功能
格式
函数、数组、结构体
1、函数作用:函数就是功能完整的功能体,就是将经常使用的代码段封装成代码块,简化程序。
2、函数定义语法
标示符 函数名(参数列表)
{
注:函数不支持潜逃定义,C和oc都不支持
3、函数调用
注:函数调用时数据传递是单向的,即只能把实参的值传递给形参,而不能把形参的值反响传递给实参。形参的值改变不能改变实参的值。
4、函数分类:库函数 自定义函数
二、数组
1、数组属于构造数据类型。一个数组可以分解为多个数组元素,这些元素可以是基本数据类型或是构造类型。
2、数组是一串连续的地址空间
3、一维数组的定义
注:数组定义必须有大小,只能存放一种类型数据,数组元素使用下标表示,下标从0开始
4、二维数组定义
数据类型 数组名称[长度][长度]={值1,值2,……}
5、在这单独说一下字符串数组
在C中没有专门的字符串常量,通常使用一个字符数组来存放一个字符串的。字符串在数组中存储时多占用一个字节存'\0'。
补充:与字符串有关的函数
(1)gets(字符数组名或字符指针变量);
功能:从stdio流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。
返回值:读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。所以在遇到返回值为NULL的情况,要用ferror或feof函数检查是发生错误还是遇到EOF。
(2)fgets函数
fgets函数用来从文件中读入字符串。
fgets函数的调用形式如下:fgets(str,n,fp);
此处,fp是文件指针;str是存放在字符串的起始地址;n是一个int类型变量。函数的功能是从fp所指文件中读入n-1个字符放入str为起始地址的空间内;如果在未读满n-1个字符之时,已读到一个换行符或一个EOF(文件结束标志),则结束本次读操作,读入的字符串中最后包含读到的换行符。因此,确切地说,调用fgets函数时,最多只能读入n-1个字符。读入结束后,系统将自动在最后加'\0',并以str作为函数值返回。
比较结果是这样规定的:
①字符串1小于字符串2,strcmp函数返回一个负值;
②字符串1等于字符串2,strcmp函数返回零;
③字符串1大于字符串2,strcmp函数返回一个正值;
实际上,字符串的比较是比较字符串中各对字符的ASCII码。
(4)strcpy(字符串1的地址,字符串2的地址);
其中,字符串1必须是字符串变量,而不能是字符串常量。strcpy函数把字符串2的内容完全复制到字符串1中,而不管字符串1中原先存放的是什么。复制后,字符串2保持不变。
其作用是谅解两个字符数组中的字符串,将字符串2接到字符串1的后面,结果放在数组1中,函数调用后得到一个函数值是字符数组1的地址。
(6)strlen(字符数组名或字符指针变量);
测试字符串长度,函数的值位字符串的实际长度,不包括'\n'在内的。
三、结构体
一、定义:定义属于自己的数据类型
struct结构体名称
};
注:解决了存储元素的类型和长度不一致的问题
二、结构体成员的访问
1、结构体变量名.成员名
2、通过指针访问:struct student *st;
三、结构体中的字节对齐问题
通过字节对齐,有助于加快计算机的取数速度,否则就得多花指令周期。
结构体默认的字节对齐一般满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员自身大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
补充:产生随机数的函数
arc4random函数
arc4random() 是一个真正的伪随机算法,而且范围是rand()的两倍。
第五章 指针
一、指针
1、指针是一个地址,指针变量是存放地址的变量,指针变量用来指向另一个变量
2、指针变量的一般形式
基类型 *指针变量名
基类型用来指定该指针变量可以指向的变量类型
3、可以用赋值语句使一个指针变量得到另一个变量的地址,从而使它指向一个普通变量。
例如 pointer_1=&i
将变量i的地址存放在指针变量pointer_1里,pointer_1就指向了变量i
4、
第一、;和普通变量一样,可以对数据进行存取,这个数据仅限于指针或者地址
第二:可以对所指向的内空间进行存取操作,如果一个指针没有指向一块区域,就对其进行读写操作是非法的1
5、pointer_1=&a;
则&*pointer_1=&a
*&a即是变量a
6、指针变量作为函数参数,它的作用是将一个变量的地址传送到另一个变量
7、数组元素的指针就是数组元素的地址
8、注意 int a[10];int *p下面两个语句是等价的 p=&a[1]; p=a;
这里数组名a不代表整个数组,p=a;代表是把a数组的首元素的地址赋值给指针变量p,并不是把数组a的各个元素的地址赋值给p
二、指针数组和数组指针
1、指针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量
2、指针的移动必须 基于数组指针
注:数组不支持自身运算
三、结构体指针
1、一个机构体变量的指针就是该变量所占据的内存段的起始地址。指针变量也可以用来指向结构体数组中的元素。
补充:malloc函数和free函数
1、malloc函数
malloc()函数其实就在内存中找一片指定大小的空间,然后将这个空间的首地址范围给一个指针变量,这里的指针变量可以是一个单独的指针,也可以是一个数组的首地址,这要看malloc()函数中参数size的具体内容。我们这里malloc分配的内存空间在逻辑上连续的,而在物理上可以连续也 可以不连续。对于我们程序员来说,我们关注的是逻辑上的连续,因为操作系统会帮我们安排内存分配,所以我们使用起来就可以当做是连续的。
原型:extern void *malloc(unsigned int num_bytes);
虽然malloc()函数的类型是(void *),任何类型的指针都可以转换成(void *),但是最好还是在前面进行强制类型转换,因为这样可以躲过一些编译器的检查。
功能:开辟一段内存空间
返回值: 指针或者指针指向开辟空间的首地址
形参 : 开启空间的字节数
调用格式,比如想分配100个int类型的空间:
int* p = (int *) malloc ( sizeof(int) * 100 ); //分配可以放得下100个整数的内存空间。
其他数据类型类推
2、free函数
该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。
原型:void free(void *FirstByte);
注:free()释放的是指针指向的内存,不是指针。指针是一个变量,只有程序结束时才被销毁。例如你用free( p )释放了内存空间后,原来指向这块空间的指针还是存在!此时原本指向刚刚释放掉了空间的指针p仍然指向了该内存空间,这样一旦这段内存已经被别的变量使用的话,就可能误用p来修改这里的值,这不是我们所期望的,所以free(p)之后一定要将p = NULL;,这样就万无一失了。
四、指针的指针:指的是指针变量的地址
与二维数组的结合
例题 分析如下
分析:由第二行知道指针变量p指向的类型是 int[2]型,*p是a的首地址,也就是元素10的地址,因为是int[2]型,所以 *(p+1)是30的地址,而不是20 的地址;20 的地址是*p+1;其他类推
**p就是元素10,*(*(p+2)+1)就是元素60
五、函数的指针
指向函数的指针,然后通过指针调用函数
语法:
调用:
宏、枚举
是预处理命令,不是c语言本身的一部分,不能直接对他们进行编译。
注:原封不动的替换
#define
带参数的宏定义
#define MAX1(A,B)(A>B)?A:B
int a=MAX(3,5);
二、枚举
是一种数据类型。几种取值可能逗列出来
是一组相关的常量值,多用于传参
定义形式
enum 枚举名{枚举值表};
枚举类型其实就是整形,%d
三、static和const关键字
1、static关键字定义静态变量
在函数体,一个被声明为静态的变量在函数被调用的过程中维持其值不变。其值是放在静态区的。在程序整个运行期间都不释放。在编译时赋初值,即只赋值一次,也就是在完成第一次操作过程后,当第二次操作时,先检测静态区的值。不在执行现有的赋值语句
如果不赋值的话,编译时默认变量值为0
注:静态变量在程序加载时就分配内存
补充:auto自动变量
这种存储类型是C语言程序中使用最广泛的一种类型。C语言规定, 函数内凡未加存储类型说明的变量均视为自动变量, 也就是说自动变量可省去说明符auto。函数中的形参和在函数中定义的变量(包括在符合语句中定义的变量)都属于这一类的。 在前面各章的程序中所定义的变量凡未加存储类型说明符的都是自动变量。
其值放在动态区,函数调用结束后即释放。自动变量赋初值是在函数调用时进行,每调用一次函数重新赋值一次,每次都会执行现有的赋值语句。
2、const
用来修饰不允许改变的变量
注:const与#define的区别是,前者是运行 是内存中实际存在,后者编译期进行处理
const应用
常量定义代替#define
函数参数定义
注:const