c语言作业 万能公式,C语言基础笔记

本人学习期间总结的所有C语言笔记:

1.运算符

一元运算符优先级大于二元运算符

,运算符优先级最低

[]大于*号运算符(用于指针数组时)

! > 算术运算符 > 关系运算符 > && > || > = > ,

2.字符型

char没有明确的定义为signed或unsigned,如果需要注意,要自己加上

'\''    '\"'    '\\'    '%%'    '\?'

警报'\a'        回退'\b'        换页'\f'        换行'\n'        回车'\r'        水平tab'\t'    垂直tab'\v'

getchar();从stdin缓冲区中读取

getch();从键盘缓冲区中读取,在win下不回显,在Unix下回显 在中

字符测试函数:【包含在中】

1) int isalnum(int c)      //测试c是否是字母或数字,是的话返回为真,否则为假

2) int isdigit(int c)      //测试c是否是数字

3) int isalpha(int c)      //测试c是否是字母

4) int islower(int c)      //测试c是否是小写字母

5) int isupper(int c)      //测试c是否是大写字母

6) int tolower(int c)      //转换为小写字母

7) int toupper(int c)      //转换为大写字母

8) int iscntrl(int c)      //测试c是否是控制字符

9) int isspace(int c)      //测试c是否是空格

10)int isgraph(int c)      //测试c是否是除了空格外的可打印的字符

11)int isprint(int c)      //测试c是否是可打印字符

12)int ispunct(int c)      //测试c是否是除了空格,数字,字母外的可打印字符,即是否为符号

3.字符串

字符串就是一个字符数组,结尾以'\0'作为标志

一个字符占用一个字节(汉字占用两个字节),从左到右依次存放,在字符串的结尾自动加入一个字节的结束标志'\0'

'a'与"a"的不同:'a'代表一个字符占用一个字节;"a"代表一个字符串占用两个字节.

字符串初始化:char str[10]="abc123!@#";//不能写成char str[10];str="dfh";(初始化声明的时候的=不代表赋值操作,只是初始化)

gets()

puts()

字符串转换函数:

1)int atoi(const char *str)        //将字符串类型的数据转换为整型,参数为字符串首地址

2)double atof(const char *str)        //将字符串类型的数据转换为双精度浮点数

字符串库函数:

1) strlen()

2) strcpy()    strncpy()【复制指定字符个数的字符串】char *strncpy(char *s1, const char *s2, size_t n);

3) strcmp()    int strncmp(const char *s1, const char *s2, size_t n);【比较前面n个字符】

4) strcat()    可以用在这种情况下:char ping[8]="ping ",ip[32]="www.baidu.com"; strcat(ping,ip); system(ping);

5) strtok()    字符串分割函数以s2为标准分割s1,char *strtok(char *s1, const char *s2);

6) bzero(void *s, size_t n)    字符串清理,参数1是要清空的字符串,参数2是要清空的位数

7) memset(void *s, int c, size_t n)    字符串填充,参数2为填充进去的内容,参数3为要填充的字节数

8) strchr(const char *s, int c)        在s中查找c第一次出现的地址

9) strrchr(const char *s, int c)    在s中查找c最后一次出现的地址

10)strstr(const char *s1, const char *s2)    在s1中查找s2第一次出现的地址

4.变量(Mac下)

int    4个字节        -2e15~2e15-1

float    4个字节        有效位数6~7位

double    8个字节        有效位数15~16位

char    1个字节        ASCII码字符,或-128~127

定义一个变量时,系统就自动的分配了空间,未赋值前,是随即放入的一个垃圾值

5.无符号、×××10进制、8进制、16进制

正常:u   d   o   x

短: hu  hd  ho  hx

长: lu  ld  lo  lx

6.浮点数

默认情况下,浮点数是以双精度存储的,要明确使用的是单精度,要在数字后面加上字母f(如:57.0f),如果必须以long double格式存储,要在数     字的末尾加上字母l(如:57.0l)。

当读取double类型的数值时,在e、f、g前放置字母l,但是l只能在scanf中使用,不能在printf中使用,在printf中e、f、g就能表示double型

当读或写long double类型的值时,在e、f、g前放置字母L;

7.scanf函数和printf函数

scanf函数在读入数字时,会自动跳过空白字符,但在读入字符时,不会跳过空白字符

读写一个单独的字符时,可以用getshar和putchar代替:[ch=getchar();    putchar(ch)]

8.sizeof(类型名)

sizeof返回的值是无符号的整数

可以用sizeof(a)/sizeof(a[0])计算数组长度

9.类型定义(typedef)

typedef int Bool;    //(后面变量名的首字母最好大写)

Bool flag;    //类似与使用了int flag

C语言库自身使用typedef定义了一些不同的类型名,这些类型名通常以_t结尾,比如clock_t;

10.宏定义

【定义宏】#define BOOL int

数组和指针不能用宏定义,宏定义中的替换列表为空也是合法的,也可以包含对另一个宏的调用,但宏不能调用它本身.

一个数字常量,如果不是0和1,就最好定义成宏.

【带参数的宏】 #define  标示符(x1,x1,…,xn)  替换列表    //参数在替换列表中都要放在圆括号中

#运算符将一个宏的参数转换为字符串字面量;##运算符可以将两个记号(如标示符)粘在一起,成为一个记号.

#define CONCAT(x,y)  x##y    //CONCAT(a,b)会得到ab,但CONCAT(a,CONCAT(b,c))不会得到abc,而是aCONCAT(b,c)

【在宏中放入语句】放在do{ … }while(0)中,这时while后可以不加分号,在调用宏的时候再加分号;如果定义的时候就有分号,在调用的时候就不能再加分号了.

【取消宏】#undef 标示符

【预定义宏】_DATE_宏(mm dd yyyy)和_TIME_宏(hh:mm:ss)指明程序编译的时间,是字符串字面量.

_LINE_宏: 被编译的文件的行数,是整型常量    _FILE_宏: 被编译的文件的名字,是字符串字面量

_STDC_宏: 如果编译器接受标准C,值为1,是整型常量

11.数组

定义数组时,数组名不能和变量名相同,也不能和系统关键字一样

数组的地址就是数组元素的首地址,使用数组名a,代表的就是数组a[]的地址

多维数组:不常用,因为指针数组更加的灵活好用

无论是一维数组还是多维数组,通过单词const作为数组声明的开始可以把数组变为“常量”;

(如:const int months[]={31,28,31,30,31,30,31,31,30,31,30,31};)

12.函数

在调用函数前,都需要先声明函数,函数声明类似与函数定义的第一行,函数的声明必须与函数的定义一样。

【函数声明】 返回类型  函数名(形式参数);    【编译器只预处理函数,但是不分配内存】

【函数定义】 返回类型  函数名(形式参数)    【开辟内存空间,分配内存给函数,函数入口地址为函数名所在地址】

{

声明

语句

}

【函数调用】 函数名(实参);

函数无法返回数组;如果忽略返回类型,会假定为int型;

如果返回为空类型,必须写明void,如果没有形参,也要写明为void.如:void function(void)

数组做函数参数的时候,传递的是数组名,也就是地址

实参是通过值来传递的,在调用函数时,计算出实参的值然后传递(赋值)给对应的形参

函数分类:

1)从用户角度分有:

系统函数:库函数,不需要用户定义,包含头文件就可以直接使用的函数,printf();scanf();system();

自定义函数:用户根据自己的需要,声明函数的返回值类型,函数名,形参列表;但是必须符合函数声明的规则。可以是有参、无参、有返回值、无返回             值、还可以是函数的重写。

2)从返回值的角度:

有返回值:return,(函数有且只能返回一个返回值),可以是基本数据类型和指针等。

无返回值:void,在C89标准中可以忽略返回值类型,UNIX中默认为int,Window VC中为void;在C99标准中不可以忽略返回值类型。

3)从参数的角度:

带参数:需要告诉编译器参数的类型和数量

int main(int argc,char *argv[]);

int main(int argc,char **argv);

不带参数:参数列表为空,void,可以省略,即int main()或int main(void);就是不需要参数来参与运算。

13.返回语句

return:【return 表达式】如果return中表达式的类型和函数返回的类型不一致,系统会把表达式的类型转换成返回类型

exit:任何函数中都可以使用,【exit(表达式)】;包含在#include 头文件中。

main函数的返回值是状态码,0表示正常结束,非0为异常结束。

14.递归

递归是函数嵌套调用的一种特殊形式,就是当一个函数调用另外一个函数的过程时,另一个函数恰好是它本身。

递归产生的条件:直接或间接的调用它本身,有一个出口(即结束递归的条件),要有一个明显的公理或公式,有规律可循。

1)直接递归调用

2)间接递归调用

注意:

1)递归调用在发生时,消耗了大量的系统资源,反复读写栈内存,CPU资源,会降低系统性能,不可控或深层递归都会造成系统不稳定

2)我们在开发过程中使用的都是浅层递归,如Windows搜索,使用了多线程,浅层递归(一般不超过3层)

3)递归调用也被用于分治算法

4)能不用就不用递归,如:.(){ .|. };.  (.本身是一个函数,()为.函数的参数列表,;前为.函数的定义,最后一个.是调用这个函数)

15.迭代

迭代法又叫做递推,凡是能用递归来实现的迭代或递推都能实现。

八皇后问题,水仙花束问题,兔子繁殖问题,约瑟夫出圈问题,快速排序,汉诺塔

16.变量作用域

全局变量:

局部变量:

17.指针

简单的说,指针就是地址。

内存中的最小存储单元是字节,一个字节有8位,每一位都有自己的地址,指针就是他们的首地址。

基本数据类型的指针,就是他们在内存中的首地址。

构造类型的指针,数组,他的位置就是,数组名称所在内存的首地址,即a[0]的地址或者是数组名。

函数类型的指针,就是函数的入口地址,即函数名所在内存的首地址。

指针变量:和其他基本数据类型的变量类似,特殊的是他是能保存地址的变量。

【定义指针变量】类型标示符 *变量名(int *p);

指针变量初始化:

int *p=NULL;

int *q=&a;

int *s=100;

造成野指针的三种方式:

1.定义指针的时候没有初始化

2.指针指向一个局部变量,当局部变量执行完毕释放后,仍然指向该局部变量的时候(用完置NULL即可)

3.当指针指向一块动态的内存空间时malloc(new)使用完毕被free(delete)释放后,仍然指向该空间,(用完置NULL即可)

18.指针和常量的关系

1)常量指针:

指针指向了一个常量的指针变量,常量的内容不可以修改,但是地址可以修改。

int const *p;    const在*号后,是p的值不能修改;const在*号前,是*p的内容不能修改

2)指针常量

是个常量,是指指针变量P的值不能被修改,p是个常量,而指针指向的对象的值是可以改变的。

int *const p;

19.指针和数组的关系

1)数组指针

指向一维数组的指针,即数组的首元素

int a[10];int *p=NULL;p=a;

是一个指向二维数组一行的指针变量,即二维数组的首行的地址

int (*p)[表达式];

2)指针数组

数组元素是指针变量

int *p[表达式];

20.指针和函数的关系

1)函数指针

就是指向函数名的指针变量

int (*p)(形参列表);

2)指针函数

它是一个返回指针类型的函数,即函数的返回类型是指针

int *p(形参列表);

如:int *adr(int x)

{

return &x;

}

这种情况,返回值还可以继续作为函数的参数来使用,如回调函数,比如Unix信号和信号量,signal(),malloc()

21.指向指针的指针

int a=0;  int *p=&a;  int **q=&p;    //*p==a,  **q==a

22.结构体(struct)

能够保存不同数据类型的一种构造数据类型

【关键字】struct

【定义结构体】    struct 结构体名{

成员变量1;

成员变量2;

成员变量n;

};    //分号表示结构体定义完毕

【结构体变量初始化】(结构体变量就是包含结构体所有属性的一个变量)

struct struct_name 变量名={ , , };    //struct struct_name 整体是变量的类型

或    struct struct_name{

成员变量1;

成员变量2;

}object_name={ , , };

【引用结构体成员变量】

.   或  ->(用于指针的时候)

【结构体和指针】

1)指向结构体的指针

struct struct_name *p;    //p是指针变量名

p=&object_name;        //&取地址符不能忘

【结构体的嵌套】

一个结构体中嵌套了另一个结构体

struct struct_name{

成员变量1;

成员变量2;

struct struct_name_a{

成员变量a;

成员变量b;

}object_name_a;

}object_name;

【引用】object_name.object_name_a.b;

【结构体变量(可以用指针)作为函数参数使用】

void struct_function(struct struct_name object_name_temp);

void struct_function(struct struct_name *p);

【结构体变量作为函数的返回值】

struct struct_name function_name()

{

return object_name;

}

【结构体数组】

数组中的每个元素都是一个结构体变量

struct struct_name{

成员变量1;

成员变量2;

}数组名[表达式];        //表达式可以为空,为空的时候是不定长度的数组

23.联合体(union)

用户自定义的数据类型,和结构体不同的是结构体变量独立使用各自成员的内存空间,联合体的所有成员共享存储空间,即使用联合体省内存.

定义联合体和结构体一样,只需要把struct改成union即可.

24.枚举(enum)

枚举的成员中只能用一种类型,成员内不指定序号的时候都以0开始,C语言把枚举变量和常量作为整数来处理

enum color{red, black, blue}a,b;    //中间以逗号隔开

25.链表

链表是线性表的一种,是线性表的链式存储;是一种使用动态内存分配的,能保存不同数据类型的一种数据结构.构成链表的最小单位称为节点.

1)单链表

有一个头结点(非空)链表,结点之间有前驱和后继,尾结点无后继结点,指向空.节点有两部分组成数据域和指针域.头结点用于判断链表是否为空.

2)双链表

3)循环链表

26.位操作

1)位与&

用于置0

2)位或|

用于置1

3)位异或^

用于加密和解密:

0000 1100    0000 0110    (用第一次异或得到的值,再进行异或)

^    0000 1010    ^    0000 1010    (用同一个值作为异或的运算)

--------------  --------------

0000 0110    0000 1100    (重新得到了之前的值)

交换a,b的值:  a=a^b; b=a^b; a=a^b;

4)位取反~

都是用补码来取反的

连带符号位一起取反,取反之后符号位为1的话(补码),减去1(反码),除去符号位其它位取反(原码)

5)左移<<

往左移,低位补0,左移一位相当于乘以2,左移n位相当于乘以2的n次方

6)右移>>

往右移,高位补符号位,右移一位相当于除以2,右移n位相当于除以2的n次方

Mac下左移右移符号位不变

27.内存管理

系统级内存管理(Unix系统提供的内存管理)

1)物理内存管理

2)虚拟内存管理

3)页面文件getpage

4)内存映射mmap

5)共享内存

brk();//在分配内存时效率很高,只有3个值:大于0(申请该大小的内存空间),等于0(完全释放内存),小于0(在当前的内存空间上释放该大小的空间)

sbrk();

OC中用的内存管理,计数,当计数为0的时候就自动释放(OC brk)

用户级内存管理

1)malloc

2)calloc

3)realloc

C语言执行过程中,在内存中的情况:

1)代码段(静态区域)

代码段由程序中的机器码组成,C语言中源代码编译后就形成了机器码,执行的时候,CPU的程序计数器指向了代码段的每一条代码,并由CPU依次执行

2)数据段(静态区域)

只读数据段,是程序使用一些不会被修改的数据,使用这些数的方式类似与查表式的操作,放置在只读存储器中;

已初始化读写数据段,是在程序中声明,有初值的变量,需占用寄存器空间,在程序执行时,位于可读写的内存区域内,供程序运行时读写

3)BSS段(未初始化读写数据段)(静态区域)

是在程序中声明,没有初始化的变量,这些变量在程序运行前不占存储器空间

4)堆空间(动态区域)

只在程序运行时出现,一般由程序员分配和释放,在具有操作系统的情况下,若程序员忘记释放,在程序结束后,系统会自动回收内存

5)栈内存(动态区域)

只在程序运行时出现,在函数内部使用的变量,函数参数及返回值,函数调用(递归)都将使用栈空间.栈空间是由编译器自动分配和释放的内存.

C语言提供的两种内存分配的方式:

1).静态内存分配(栈内存)

由编译器自动为我们分配的内存空间,一般栈内存的大小为10M~30M

内存的对齐:是指整型占4个字节,大于4个字节的数据类型,也按照4个字节来计算,而且是4的整数倍

内存的补齐:只在结构体中有,如果所占字节数不足4个数据类型,比如char,需将不足的字节数补空,补够4个字节

2).动态分配内存(malloc向堆申请内存)

malloc函数(分配后不初始化)

void *malloc(size_t size);    //返回值是万能指针,在Mac下占8个字节,在Win下占4个字节

用于动态的向堆内存申请内存空间,使用完后,要使用free()函数释放该内存

一旦指针p指向动态分配的内存块,就可以忽略p是指针的事实,并且把它用作数组的名字,p[i].

free函数

calloc函数(分配之后初始化为0)(用于存储构造类型或复合类型数据)

void *calloc(size_t nmemb, size_t size);   //有nmemb个元素,每个元素占size个字节,nmemb为1表示为任何的数据类型

realloc函数

void *realloc(void *ptr, size_t size);      //ptr指向通过malloc或calloc或realloc分配的内存块

28.预处理

预处理器的行为是由指令控制的,这些指令是由#开头的一些命令.指令总是在第一个换行符处结束,若想在下一行继,在当前行末尾用\字符.

【宏定义】 #define指令定义一个宏, #undef指令删除一个宏定义.

【文件包含】#include导致一个指定文件的内容被包含到程序中.

1)#include    //用于C语言自身库的头文件

2)#include "文件名"    //用于所有其他头文件,也包含任何自己编写的文件

3)#import  "文件名"    //被包含的头文件只被编译一次,不会重复

【条件编译】#if, #ifdef, #ifndef, #elif, #else和#endif指令将一段文本块包含到程序中或排除在程序之外.

1)#if 常量表达式    //当预处理器遇到#if时,如果表达式的值为0,在#if和#endif之间的行会在预处理过程中从程序中删除,

语句              否则,在它们之间的行会被保留在程序中,并继续被编译器处理,这时的#if和#endif对程序无任何影响.

#endif          对于没有定义过的标示符,#if会把它当做是值为0的宏对待

2)defined    仅用于预处理器,当defined应用于标示符时,若标示符是个定义过的宏返回1,否则返回0.常用在#if指令中

#if defined(BULL)

...

#endif

3)#ifdef 标示符        //等价于   #if defined(标示符)

#ifndef

4)#elif  表达式1

#else

【特殊】#error, #line, #pragma更为特殊,较少用到.

1)#error 消息

2)#line n ("文件名")    //line指令用于改变给程序行编号的方式,n在1和32767之间,之后的行编号为n+1,文件名可以没有

3)#pragma 记号        //对非常大的程序或需要使用指定编译器的特殊功能的程序很有用

29.链表

由一连串的结构(结点)组成的,其中每个结点都包含指向下一个链中结点的指针,最后的一个结点包含一个空指针.

for (p = first; p!=NULL; p = p->next)

30.文件

C程序中的流的访问是通过文件指针实现的,类型为FILE *fp;文件结束符EOF(由宏定义的);

1)打开文件

FILE *fopen(const char *filename, const char *mode);    //filename可以包含路径信息,没打开返回空指针

打开的模式(mode):

"r":只读            "w":写,文件不需要存在        "a":追加,文件不需要存在

"r+":读和写,从文件头开始        "w+":读和写,文件存在就截取        "a+":读和写,文件存在就追加

如果打开的是二进制文件,需要在模式字符串中包含字母b, 即"rb"

2)关闭文件

int fclose(FILE *stream);    //参数必须为文件指针,指针来自fopen或freopen,成功关闭文件返回0,否则返回EOF

3)为流附加文件

FILE *freopen(const char *filename, const char *mode, FILE *stream);    //stream有stdin,stdout,stderr

4)格式化输入/输出

fscanf(fp,"%d", &i)    //从fp中读入    fscanf(stdin, "%d", &i)等价于scanf("%d", &i)

fprintf(fp, "%d", i)    //从fp中读出    fprintf(stdout, "%d", i)等价于printf("%d", i)

5)字符读写函数

fgetc(fp)    getc(fp)

fputc(ch, fp)     putc(ch, fp)

6)行的输入/输出

fgets(char *s, int n, FILE *stream)    //n为限制要读入字符的数量, 为字符串的时候要额外的加1, 表示为'\0'

gets(char *s)    //逐个读取字符

fputs(const char *s, FILE *stream)    //系统不会自己写入换行符, 可以人为的加入"\r\n"

puts(const char *s)    //系统会自动写入换行符

7)块的输入/输出(主要用于操作二进制文件)

fread()

fwrite()

8)fflush(fp)    //为fp清洗缓冲区        fflush(NULL)    //清洗全部缓冲区

remove("filename")    //删除文件,参数是文件名,而不是文件指针

rename("filename", "newfilename")    //重命名文件名, 参数也是文件名,不是文件指针, 文件此时要是关闭状态

fcopy  f1.c  f2.c    //把文件f1.c复制给文件f2.c

feof(fp)

ferror(fp)

fseek    //文件位置  文件开始: SEEK_SET    文件当前位置: SEEK_CUR      文件结尾: SEEK_END

31.gcc编译的过程

预处理(Pre-processing):-E

编译器将C源代码中包含的头文件如stdio.h编译进来(.i)

编译(Compliling):-S

编译器首先检查代码的规范性, 是否有语法错误等, 以确定代码实际要做的工作, 无误后, 将代码翻译成汇编语言(.s)

汇编(Assembling):-c

把编译阶段生成的.s文件转成二进制目标代码(.o)

链接(Link):

将输出文件.o链接成最终的可执行文件

32.函数库

静态库(.a): 是指在编译链接时, 把库文件中的代码全部加入到可执行文件中, 因此生成的文件比较大, 但在运行时就不再需要库文件了.

动态库(.so): 在编译链接时, 并没有把库文件的代码加入到可执行文件中, 而是在程序执行时由运行时链接文件加载库, 节省了系统开销.

gcc编译时, 默认使用动态库.

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值