标签:
Day02 基础知识
一、变量
1.分为字符型char、整数型int、浮点型float/double、指针、结构、联合等类型。
2.每次使用之前要声明,需要声明其类型且只声明一次
int number1;//声明变量number1,并且开辟(int类型)内存空间。
3.声明一个变量,在使用之前,它是有可能有值的,但是最好给它一个初值。
int number3=0;
4.输出变量的值
%d int
%f float
%lf double
%c char
printf(“%d",number3);
Day03数据类型
一、数据类型
1.数据类型分类
a.基本数据类型
b.引用数据类型(后续再讲)
2.基本数据类型
在C语言中,基本数据类型有四种: char、int、float、double
二、字符型 char
常见字符:
‘A’= 65、 ‘a’= 97、 ‘0’= 48
1.char代表一个字符,用‘ ’括起来,占位8位(8bit)内存
2.输入函数
scanf("%c",&ch);
通过键盘向程序传输数据,等待(阻塞)用户输入。直到用户输入完毕,默认以回车为用户输入结束,control+c 强制停止程序运行。
3.转义符 \
常用的转义符处理:
\n 换行字符(下一行行首)
\r 回车字符(本行行首)
\t 制表符(相当于按tab)
三、整型 int
1.short (int) 16位,long (int)32位,long long int 代表就是64位整数。推荐int类型描述整数。
2.进制转换 自动
1).赋值
int i = 11;//默认 十进制
int i2 = 011;//八进制
int i3 = 0x11;//十六进制
2).输出
printf("i:%d i:%o i:%x\n",i,i,i);
四、浮点型 float/double
1.C语言中,浮点型包括float、double、long double。
float 32位 4字节 2^32
double 64位 8字节 2^64
long double 96位 12字节 2^96
2.输出结果时,使用占位符
%f->float
%lf->double
%g
%.2f输出的结果保留两位小数
Day04 运算符
一、常量
1.
3 -int
3L -long int
3LL -long long int
3u -unsigned int
3ul -unsigned long
2.
3.5 -double
3.5f -float
3.5L -long double
二、sizeof(参数)
1.计算出数据所占内存空间大小,以字节单位。
2.参数可以是类型、变量或表达式,但sizeof()不负责计算表达式的值,只关注类型。
3.sizeof(参数)对应的数据类型是long unsigned int->%ld
三、运算符
1.算术运算符
a.+、-、*
b./(求商)和%(求余、取模)
2.赋值运算符 =
a. 赋值从右向左
int i = 10; int j=20,k=30;
i=j=k=6; 注:不推荐
b.赋值可以和其它运算符结合使用,叫复合赋值
i+=3 -> i = i + 3
优点:+=(一个操作数) 比 = + (二个操作数)效率高
3.自增、自减运算符(++或--)
b.可用于整型变量 int/short/long、浮点型float/double和字符型char变量。
4.关系运算符
a.在C语言中,关系运算符和数学上的>、<、>=、<=相对应的,==等于、!=不等于,表达式产生结果,1(成立)或0(不成立)
b.关系运算符也可以用于比较整数和浮点数,也允许混合类型操作数。
5.逻辑运算符 &&与 、||或、 !非
a.当操作数处理结果不是1或者0时,逻辑运算符将非零操作数作为真值处理。
b.短路运算
6.取地址&和寻址运算符*
a.在变量前加上&,得到的就是变量在内存中的地址
b.在地址前使用*寻址符号,得到该地址保存的数据、值。
int i=20;
printf("%p\n",&i);
printf("%d",*&i);
7.类型转换
a.类型升级
浮点型高于整型,长整型高于短整型,有符号与无符号取有符号,在C语言中,类型转换是没有提示的。
高 long double
double
float
long long
long
低 int
b.其它转换
1)浮点型和整型运算,转换浮点型(double)后运算
2)short/char的运算转成int后运算
c.可以使用强制类型转换
目标类型 变量 = (目标类型)源类型变量;
注:类型转换的时候,实际是建立了一个新的变量(开辟了新的内存空间),原有的变量不变。
8.条件运算符 多目运算符 三目运算符
1).语法格式:条件表达式?表达式1:表达式2;
2).表达式1和表达式2为不同的基本类型时,会自动转换二者中精度较高的类型。
9.逗号运算符
表达式1,表达式2,表达式n;
1).依次计算各表达式的值,以表达式n的值作为整个表达式的结果
int result=(i=10,j=20,k=30);//30
2).并不是所有出现逗号的地方都组成逗号表达式:int i,j,k;
10.运算符的优先级
高 初等运算符:()、[]、.
| 单目运算符:!、++、--、类型转换、&、*、sizeof()
| 算术运算符:先*、/、%、后加、减
| 关系运算符:>、>=、<、<= 高于!=、==
| 逻辑运算符 : !高于&&高于||
| 条件运算符:?:
| 赋值运算符 :=、+=…复合赋值
低 逗号运算符:,
Day05 流程控制
一、开关分支(选择分支)
switch(控制表达式){
case 常量表达式1:语句;break;
case 常量表达式2:语句;break;
case 常量表达式n:语句;break;
default :语句;break;
}
控制表达式当做整型数据处理,也可以是字符型数据处理,但不能是浮点数和字符串。常量表达式必须是常量(整数和字符组成),不允许重复。
Day06 循环
一、 for循环
a.for(;;) 编译不会报错,循环次数是不确定的,死循环。ctrl+c强制终止循环。
Day07 数组
一、数组
1.声明
int array[3];
2.初始化
a.赋使用的值
int array2[3]={3,4,5};//依次给数组元素赋值
int array4[3]={1,2};//会自动用0来填充后面的值
b.赋零值
int array[3];//未初始化 可能存在垃圾时
int array3[3]={0};//数组中每个元素是0
3.取出数组元素的值
printf("array4[2]:%d\n",array4[2]);
4.数组的长度
long size = sizeof(array)/sizeof(array[0]);
二、多维数组
2.声明一个二维数组
int array2[3][2];
3.初始化
int array2[3][2]={{1,2},{3,4},{5,6}}; //依次赋值
int array2[3][2]={1,2,3,4,5,6};
int array2[3][2]={1,2,3,4};//自动补零
Day08 函数
一、函数
1.函数声明
a.返回值类型 函数名(参数);
b.函数声明可以省略参数,省略参数代表可以接受任意参数,如果不需要参数,使用void关键字。void f(void);
c.形参是数组时,采用两个参数,第一个参数是数组的长度,第二个参数是不指定数组长度的数组(数组名称)
void getSum(int length,int arr[]){}
int main()
{
int arr[]={1,2,3,4};
getSum(4,arr);
return 0;
}
e.exit(0) 两个关键字
exit(0)是一个函数,用于退出整个程序 需要包含一个stdlib.h
Day09 函数变量的作用域和生命周期
一、变量作用域
a.局部变量:定义在函数中的变量叫局部变量
b.全局变量:定义在函数外的变量叫全局变量
c.全局变量可以供多个函数使用,而局部变量只可以供当前函数使用。
d.当全局变量与局部变量重名,依然遵守就近原则。
e.参数也有作用域,是函数的内部。
二、变量生命周期
a.当修饰局部变量的时候加auto(默认),声明变量时,会创建内存空间,当变量超出作用域,就会消除相应的内存空间。
b.当修饰局部变量的时候加static,静态局部变量,此时变量的生命周期就会变长,长到程序结束为止,虽然静态变量的生命周期变长,但作用域依然在函数内部。
c.auto不可以修饰全局变量
d.static可以修饰全局变量
三、指针
1.指针指的就是内存地址。
2.保存指针的变量,就叫指针变量。
3.声明一个指针变量
int i=3;
int *p=&i;
printf("%p\n",&i);
printf("%p\n",p);//指针的值
printf("%d\n",*p);//指针指向的值
4.指针的用法:
a.指针可用于参数,传递变量的地址,就相当于多个函数共享内存地址(内存空间)。
void change(int* p1,int* p2){
int temp=*p1;
*p1=*p2;
*p2=temp;
}
int main()
{
int i=3,j=4;
change(&i,&j);
printf("%d %d\n",i,j);
}
b.指针也可以做为返回值,但不要返回自动变量,因为当函数结束局部变量会被自动清除(释放)。解决方案:延长生命周期。
c.指针支持加整数、减整数、指针的值比较和相减,但运算的单位由指针的类型决定。
int类型指针+1 = 地址+4
char类型指针+1 =地址+1
d.指针与数组
int array[3]={10,20,30};
int* p=array;
printf("%p\n",p);//指针的值
printf("%p\n",p+1);
printf("%d\n",*(p+1));//20
Day10 字符串
一、字符串
1.概念:一组字符数组,以数组的首地址为开始,以ASC的‘\0‘为结束符。
2.字符串与普通数组的区别:普通数组没有结束标识,而字符串是有的。
3.字符串的定义方式:
a.字面值 "Hello"
b.使用字符数组来定义字符串
char str[10]={‘H‘,‘e‘,‘l‘,‘l‘,‘o‘,‘\0‘};
c.使用字符指针 char* p1 = str;
printf(p1);
printf("%s",p1);
4.字符串创建方式的不同
a.声明的变量,放在内存中的栈区。
b.字面值方式创建的字符串,放在内存中的代码区如果创建的是字符串,并且值是相同的,只会创建一个内存区域,其值是只读的,值不可以改变。
c.使用数组方式创建的字符串,放在内存中的栈区,可以创建多个相同的字符串,其值可以改变。
d.字符指针,只是指向了内存的一个区域。
5.输入
a.scanf() 在输入字符的时候存在缓冲区问题
通过scanf("%*c");清除缓冲区
char name[10];
scanf("%s",name);//自动加\0
b.scanf() 在输入字符串的时候不存在缓冲区问题,但存在安全性问题(内存溢出)。
c.fgets()函数,解决安全性问题
语法格式:fgets(参数1,参数2,参数3);
参数1:保存数据的首位置;参数2:保存的长度(包括结束符);参数3:获取数据的方式
注:使用fgets方式输入数据的时候,会自动的在数据的后面加上‘\n‘
6.输出
printf()与puts不同点
printf()需要手动换行,可以多次输出字符串
puts()自动换行,只能输出一次字符串内容
char str[10];
fgets(str,5,stdin);
printf("%s\n",str);
puts(str);
const关键字
可以将变量变为只读,只可以在初始化时才可以改变变量的值,此变量就为常量。
const int* p = &i; //指针指向的值变为只读
int* const p = &i; //指针的值变为只读
7.指针数组(字符串数组)
数组中的元素是指针->指针又可以是字符串->字符串数组
1)保存多个字符串首地址
2)定义指针数组
char* array[3]={ "guanyu","zhangfei" ,"liubei" };
3)遍历
for(int i = 0 ;i<3;i++){
printf("array[%d]:%s\n",i,array[i]);
}
8.C语言字符串函数库
a.#include <string.h>
b.字符串的复制 strcpy(str2,str)
c.字符串的拼接 strcat(str3,str)
d.字符串的长度 strlen(str),求字符串的长度,不包含结束符
char str[10];
char* p1="hello";
char* p2="you";
strcpy(str,p1);
strcat(str,p2);
unsigned long len=strlen(str);
printf("%lu\n",len);//8
e.两个字符串比较 strcmp(str,str1),结果为0时,两个字符串相等。
char str1[10]={‘a‘,‘b‘,‘c‘,‘\0‘};
char* str2="abc";
int result=strcmp(str1,str2);
printf("%d",result);
二、宏
宏相当于文本的替换操作
1.宏定义
a.定义在函数的外面
b.格式:#define PI 3.14//在编译前将PI的内容替换成3.14
c.宏与全局变量的区别
1)宏相当于文本的替换操作,内存中不存在
2)全局变量在内存中就存在的
2.宏函数:#define MianJi(r) PI*r*r//注意参数是没有数据类型
Day11 大型程序与复合类型
一、宏
1.#x 代表把x内容转换字符串
#define STR(x) #x
2.##x 代表将标识的内容与其它内容拼接在一起成为新的标识
3.C语言内部预定义的宏
__LINE__ 当前行号
__FILE__ 当前的文件名
__DATE__ 当前的日期 printf("%s\n",__DATE__);
__TIME__ 当前的时间
__STDC__ 是否是C语言的标准 返回值为0或1
__STDC__ ?"符合":"不符合"; printf("%d\n",__STDC__);
#define QUANJU(x) g_##x
int QUANJU(i) = 20;
#define STR(x) #x
#define Globel(x) g_##x
int Globel(i)=30;
int main()
{
int i=20;
printf("%s\n",STR(3));
printf("%d\n",Globel(i));
}
二、大型软件开发
1.操作步骤
a.原来只有一个文件main.c 输入函数 输出函数 声明
b.多人开发 将原文件拆分成三个文件,分别为*.h、*.c、main.c
c.编译的时候
1)分别编译不同的源文件,生成相应的目标文件 gcc -c input.c=>input.o
2)可以将多个目标文件链接生成同一个可执行文件
gcc input.o main.o=>a.out
3)在main.c文件中,记的导入头文件
3.如果想在一个项目中共享全局变量,在使用的文件中,要使用extern关键字,声明变量,才可使用,并且可以得到全局变量的值。
4.全局变量前可以加static修饰符,该全局变量只能在当前文件中使用,static也可以修饰函数。加了static的变量,就是私有变量,加了static的函数,就是私有函数。
三、结构体
1.结构体的格式
struct{
成员;
}变量名;
typedef struct{
int age;//成员
char name[20];
}Student2;//别名
2.结构体使用:
Student2 stu = {17,"lisi"};
stu.age = 18;
printf("name:%s age:%d\n",stu.name,stu.age);
3.如果结构体中的成员是字符串,是不能通过=进行赋值的,要使用:
strcpy(student2.name,"zhangsan");
4.结构体的定义部分是不占用内存的,所以可以把结构体的定义放到头文件中,项目中的其它文件就可以使用该类型。
5.如果是基本数据类型,使用结构类型的变量.成员,可以操作该成员。
6.声明结构体类型的变量,占的空间为所有成员类型所占空间之和?边界对齐 sizeof(Student2)
7.如果使用结构体变量赋值,相当于将结构体中每一个成员的值,都赋给新的结构体变量的成员。
四、联合
1.联合的用法、语法和结构非常相似,但联合中所有成员分配的内存是同一块。(只能保存一个成员信息,联合的空间以最大成员所占的空间为值)
2.联合可以用一块内存对应多种数据类型
3.联合与结构的区别,结构可以保存多个成员信息,而联合只能保存一个成员信息且最后一个。
typedef union {
int age;
char name[2];
}LianHe;
五、枚举
1.定义一个枚举
enum{SPR,SUM,AUT,WIN};//0123
2.枚举的默认值从0开始 ,每个值都是一个整型常量
3.只能在声明枚举的时候,修改枚举值
enum{SPR,SUM=2,AUT,WIN};//0234
4.修改后的枚举值=上一枚举值加1
typedef enum{SPR,SUM,AUT,WIN} SEASON;
void printSeasonByNum(SEASON season){
switch (season) {
case SPR:printf("春!\n"); break;
case SUM:printf("夏!\n"); break;
case AUT:printf("秋!\n"); break;
case WIN:printf("冬!\n"); break;
}
}
Day12 高级指针
一、高级指针
1.堆内存的动态内存分配
内存分为几个部分:
栈区 变量
代码区 字符串
全局区 全局变量
堆区 (自己创建、自己回收、变量、字符串)
2.为了从堆中动态分配内存,要指定字节个数的空间,返回首地址,如果失败返回NULL(空)。
包含头文件stdlib.h,基本的内存操作都写好了。
3.malloc函数,可以从堆中分配指定的字节个数的空间,返回首地址,如果失败返回NULL。
4.calloc函数,使用之前会把分配到的所有字节都清0。(初始化)
5.realloc函数,可以调整已经分配的空间,有两种情况,如果当前位置可以调整,在原位置调整,如果当前位置不可以调整,换一个新的位置。
6.free函数,用于释放(回收),从堆中分配的空间(内存。)
二、malloc函数
1.引入头文件stdlib.h
2.堆中没有变量名,只能通过指针的方式拿到内存中的数据(值)。
3.在使用堆内存指针的时候,最好使用const关键字修饰一下。
int* const p = ……;
4.malloc函数可以分配堆内存,字节为单位的大小。 malloc(sizeof(int)*3)
5.if (point!=NULL) 语句避免内存分配失败,造成程序崩溃,非空(安全)验证。
6.堆内存使用完毕后,一定要释放:free(point);
三、calloc函数
参数1:元素个数
参数2:每个元素所占空间大小
calloc函数分配内存时,会做清0操作。
//int* const p=malloc(sizeof(int)*3);//堆内存
int* const p=calloc(3,sizeof(int));
if(p!=NULL){
int i;
for(i=0;i<3;i++){
scanf("%d",p+i);
}
for(i=0;i<3;i++){
printf("%d\n",*(p+i));
}
}
free(p);
四、realloc函数调整内存空间
1.分配空间
参数1 调整哪个空间
参数2 调整后的大小
realloc(point, sizeof(int)*5)
2.可能出现的情况
realloc(NULL, 5*sizeof(int));相当于malloc()
realloc(point, 0);相当于free()
3.如果原来位置可以调整空间,就在原来位置调整
4.如果原来位置不可以调整空间,程序会自动在新的位置创建空间,并且将原来的值移动到新的位置,并自动释放原来的空间。
五、函数指针
1.用指针存储代码区函数的地址,所有的函数都是指针,函数名就是函数指针。
2.函数指针可以做参数,可以传入。函数指针的参数类型和返回类型完全一致。->Block
void func(){
printf("hello!");
}
int main(){
//函数指针
printf("%p\n",func);
printf("%p\n",&func);
//函数指针变量
void(*func_ptr)(void)=func;
func_ptr();
}
六、void*
1.代表任意类型的指针,malloc分配堆内存时,由于无法确定内存存储类型,所以可以使用void*代表任意指针类型。
2.不能直接对void*指针进行*操作,可以进行类型转换,然后再进行*操作。
3.void*能进行加减操作,但以1字节为单位进行运算,所以说想向void进行加、减操作,最好先转换数据类型。
typedef enum{INT,CHAR,FLOAT,DOUBLE} type;
void func2(void* p,type t){
switch(t){
case INT:printf("%d\n",*((int*)p));break;
case CHAR:printf("%c\n",*((char*)p));break;
}
}
int main(){
int i=10;
char j=‘A‘;
func2(&i,INT);
func2(&j,CHAR);
}
标签:
原文地址:http://www.cnblogs.com/iceland/p/4773377.html