C语言知识点总结

来源:互联网 发布:java calendar. Date 编辑:程序博客网 时间:2024/05/17 03:37

C语言的数据类型


数据类型包括:基本数据类型、构造数据类型和指针类型。
基本数据类型有:整形(short int、int、long int),实型(float、double、long double),字符型char。
构造类型有:数组、结构体struct、枚举型enum、共用体union。
注:数组说白了就是一个容器;枚举就是为了限定数据选择
二、规定不同的数据类型是为了计算机内部方便作数据处理,占多大内存空间
三、常量与变量
1、常量:值不可改变的数据对象。
(1)整形常量
        i 十进制
        ii 八进制     0
        iii 十六进制  0x
  (2)实型常量
         i 小数形式
         ii 指数形式 2.45e-2  
               注:e大小写是一样的,e前面的数字不能省,后面的数字必须是整数
          iii 双精度实数
  (3)字符常量:普通字符常量和转义字符常量
普通字符常量:用单引号扣起来
转移字符常量:一对单引号扣起来并以"\"开头的字符序列。如'\n'
(4)字符串常量:使用(" ")括起来的字符序列
注:注意字符常量是(' ')。长度位n的字符串在计算机中存储占n+1个字节,最后一位存的是NULL,在c中也用\n表示。
(5)符号常量
定义有两种方法:const int AGE=100;
                              #define NAME "zhangsan"
引入符号常量有两个好处:
  增加可读性
  增强程序的可维护性
补充:#define和const 的区别
第一点:#define常量在程序变异预处理的时候就万封不动的替换了,在运行时并不实际存在;const常量在程序执行阶段仍有效;
第二点:#define常量运行时已经不存常量,因此不会为其分配内存;const常量实际上定义了一个其值不能修改的变量定,因此在堆栈上为其分配了空间;
第三点:#define常量替换后被编译进程序文件的代码段,const常量存在程序文件的数据段。
2、变量:相对于可以赋值
定义形式:    类型 变量名称
变量的数据类型转换:隐式转换(自动转换)          显示转换(强制转换)
(1)自动转换:发生在不同数据类型的量混合运算时,由编译器系统自动完成。
注:第一:所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算。
        第二:char型和short型参与运算时,必须先转换成int型。
(2)强制转换
形式为       (类型说明符) (表达式)
四、运算符和表达式
1、运算符
优先级总结:初等运算符()[ ] ->  .
                       单目运算符 !
                       算术运算符  + - * /
                       关系运算符
                       逻辑运算符(不包含!) &&》||
                       条件运算符
                       赋值运算符
                       逗号运算符
自增、自减运算符分析
++i   i自增1后再参与其他运算
--i    i自减1后再参与其他运算
i++  i参与运算后,i的值在自增1
i--  i参与运算后,i的值在自减1
2、表达式
算术表达式 注:%取余 要求参与运算的都是整数
赋值表达式   注:赋值的左边只能是一个变量
复合赋值表达式  a+=1;
自加表达式
逗号表达式 优先级最低,表达式的数值是最右边那个表达式的数值 如(2,3,4)的表达式的值就是4


 分支、循环


一、3种结构:顺序、判断、循环
1、判断:if、switch
if三种形式:第一、if(表达式)语句
                     第二、if(表达式)语句1  
                                 else  语句2
                       第三、if(表达式1)语句1;
                                 else  if(表达式2)语句2;
                                  ….
                                  else 语句n;
注:if语句可以嵌套
switchi只支持整数相等判断   使用相对少
2、循环控制:for 、while、do while
(1)for(表达式1,表达式2,表达式3)      
        {语气块4}
      注: 表达式1 初值
      表达式2 循环条件
      表达式3 步长变化
      执行顺序 表达式1 表达式2  语气块4  表达式3 表达式2 判断真假进行循环
       表达式1只执行一次
(2)while与do while 主要区别是后者先执行在判断,因此至少执行一次。
(3)break表示终止循环
     continue 表示终止当前这一次循环进入下循环
二、本章涉及到的函数
1.scanf 函数
    scanf()函数是格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。
 其调用格式为: scanf("格式化字符串",地址表);
    scanf()函数返回成功赋值的数据项数,读到文件末尾出错时则返回EOF。
     如:
  scanf("%d,%d", &a, &b);
  如果a和b都被成功读入,那么scanf的返回值就是2
  如果只有a被成功读入,返回值为1
  如果a和b都未被成功读入,返回值为0
  如果遇到错误或遇到end of file,返回值为EOF。
  且返回值为int型.
注:对于字符串数组或字符串指针变量,由于数组名和指针变量名本身就是地址,因此使用scanf()函数时,不需要在它们前面加上"&"操作符。
 常用的格式符总结:
%d  输入输出整型数据                %ld  输入输出长整型数据
%c  输入输出字符型数据            %f输入单精度型数据 输出单(双)精度浮点型数据
%lf  输入双精度型数据                 %s输入输出一个字符串
 %u  输入输出无符号型整型         %o  输入输出八进制数
%x    输入输出十六进制数
2、printf函数
功能  通过标准输出设备输出一组数据
格式  printf("格式控制",输出表列),格式控制由要输出的文字和数据格式说明组成。要输出的的文字除了可以使用字母、数字、空格和一些数字符号意外,还可以使用一些转移字符表示特殊的含义。
 

函数、数组、结构体


一、函数
1、函数作用:函数就是功能完整的功能体,就是将经常使用的代码段封装成代码块,简化程序。
2、函数定义语法
标示符 函数名(参数列表)
{
  代码;
  return 返回值;
 }
注:函数不支持潜逃定义,C和oc都不支持
       函数标示符表示返回类型 标示符是void是无返回值
       形式参数列表可以为空,表示没有参数,当无参数时,函数后面的()也是要写的
3、函数调用
 函数名(实参列表)
注:函数调用时数据传递是单向的,即只能把实参的值传递给形参,而不能把形参的值反响传递给实参。形参的值改变不能改变实参的值。
4、函数分类:库函数 自定义函数
二、数组
1、数组属于构造数据类型。一个数组可以分解为多个数组元素,这些元素可以是基本数据类型或是构造类型。
2、数组是一串连续的地址空间  可以存储多个同类型的变量   就是容器 类型比较单一
3、一维数组的定义
 数据类型 数组名称[长度]={值1,值2,……}   只能存储同一类型
注:数组定义必须有大小,只能存放一种类型数据,数组元素使用下标表示,下标从0开始
       数组定义好了,不能对数组惊喜整体操作,只能一个个元素赋值或输出,使用for遍历数组个元素。
        可以对数组部分元素进行赋值,未赋值的元素自动取为0.
4、二维数组定义
数据类型 数组名称[长度][长度]={值1,值2,……}   只能存储同一类型
5、在这单独说一下字符串数组
在C中没有专门的字符串常量,通常使用一个字符数组来存放一个字符串的。字符串在数组中存储时多占用一个字节存'\0'。
补充:与字符串有关的函数
(1)gets(字符数组名或字符指针变量);
功能:从stdio流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串。
返回值:读入成功,返回与参数buffer相同的指针;读入过程中遇到EOF(End-of-File)或发生错误,返回NULL指针。所以在遇到返回值为NULL的情况,要用ferror或feof函数检查是发生错误还是遇到EOF。
 注意:本函数可以无限读取,不会判断上限,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值,为了避免这种情况,我们可以用fgets()来替换gets()。这个事实导致gets函数只适用于玩具程序。
(2)fgets函数
fgets函数用来从文件中读入字符串。
fgets函数的调用形式如下:fgets(str,n,fp);
此处,fp是文件指针;str是存放在字符串的起始地址;n是一个int类型变量。函数的功能是从fp所指文件中读入n-1个字符放入str为起始地址的空间内;如果在未读满n-1个字符之时,已读到一个换行符或一个EOF(文件结束标志),则结束本次读操作,读入的字符串中最后包含读到的换行符。因此,确切地说,调用fgets函数时,最多只能读入n-1个字符。读入结束后,系统将自动在最后加'\0',并以str作为函数值返回。
 (3)strcmp(字符串1的地址,字符串2的地址);
比较结果是这样规定的:  
①字符串1小于字符串2,strcmp函数返回一个负值;
②字符串1等于字符串2,strcmp函数返回零;
③字符串1大于字符串2,strcmp函数返回一个正值;
实际上,字符串的比较是比较字符串中各对字符的ASCII码。
(4)strcpy(字符串1的地址,字符串2的地址);
其中,字符串1必须是字符串变量,而不能是字符串常量。strcpy函数把字符串2的内容完全复制到字符串1中,而不管字符串1中原先存放的是什么。复制后,字符串2保持不变。  
  (5)strcat(字符数组1,字符数组2);等价于strcat(字符串1的地址,字符串2的地址);
其作用是谅解两个字符数组中的字符串,将字符串2接到字符串1的后面,结果放在数组1中,函数调用后得到一个函数值是字符数组1的地址。
(6)strlen(字符数组名或字符指针变量);
测试字符串长度,函数的值位字符串的实际长度,不包括'\n'在内的。
三、结构体
一、定义:定义属于自己的数据类型
struct结构体名称
 {
        类型 变量名1
        类型  变量名2
};
注:解决了存储元素的类型和长度不一致的问题
二、结构体成员的访问
1、结构体变量名.成员名  如stu.name[2]
2、通过指针访问:struct student *st;  st=&st1;(*st).num或sy->num
三、结构体中的字节对齐问题
通过字节对齐,有助于加快计算机的取数速度,否则就得多花指令周期。
结构体默认的字节对齐一般满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员自身大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
补充:产生随机数的函数

arc4random函数
arc4random() 是一个真正的伪随机算法,而且范围是rand()的两倍。
 int i = arc4random() % 100;


第五章 指针
一、指针
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、指针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量
      数组指针是指针,是指向数组的指针。
      数组下标取值本质上是地址偏移,如a[2]等同于*(p+2)    
       p++即p的地址值加上sizeof(类型)
2、指针的移动必须 基于数组指针
     +   指针向后移动一个单位    必须是数组     -  指针指针向前移动一位  
注:数组不支持自身运算  a[]++是不对的  因为数组地址是常量 指针是变量 但是可以作运算的p++是对的
三、结构体指针
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;,这样就万无一失了。
四、指针的指针:指的是指针变量的地址
与二维数组的结合
例题 分析如下
        int a[3][2]={10,20,30,40,50,60};                                                 10          20
        int (*p)[2]=a;//二维数组的指针                                                        30          40
        printf("**(p+2)=%d\n",**(p+2));                                                  50          60
        printf("**p+2=%d\n",**p+2);
        printf("*(*(p+2)+1)=%d\n",*(*(p+2)+1));
        printf("**p=%d\n",**p);
        printf("**p+1=%d\n",**p+1);
        printf("**(p+1)=%d\n",**(p+1));
        printf("**(p+2)=%d\n",**(p+2));
分析:由第二行知道指针变量p指向的类型是 int[2]型,*p是a的首地址,也就是元素10的地址,因为是int[2]型,所以 *(p+1)是30的地址,而不是20 的地址;20 的地址是*p+1;其他类推
**p就是元素10,*(*(p+2)+1)就是元素60
五、函数的指针
指向函数的指针,然后通过指针调用函数
语法:  返回类型 (*指针名)(参数列表)
调用:  指针名(参数列表)

宏、枚举


一、宏
是预处理命令,不是c语言本身的一部分,不能直接对他们进行编译。
注:原封不动的替换     宏一般使用大写      末尾不加分号
         宏定义可以嵌套  
#define  COUNT 100
带参数的宏定义
#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  int*a; 指向长整形的指针  修饰指针执行的内容 内容不可改变 可改地址
      int *const a;指向整形数的常指针   修饰指针 内容可改变  地址不可变
0 0
原创粉丝点击