C入门学习笔记

常量

1、常量概念:不可改变的量 也不可修改

2、常量类型

整形 浮点型 字符型 指针 字符串

变量

1、变量概念 可以被修改的的的量

2、变量类型 (基于64位操作系统)

整形 int 4个字节 短整形 short 2个字节 长整型 long 8个字节

浮点型 单精度 float 4个字节 双精度double 8个字节

字符型 char 1个字节

3、float在内存中存储形式

无论是单精度还是双精度在存储中都分为三个部分:(单精度 32 位 双精度 64 位)

a、符号位 :0 正 1 负 单双都是1位

b、指数位:用于存储科学计算法中的指数数据,并且采用移位存储 单精度 8 位 双精度 11位

c 、尾数部分:尾数部分 单精度 23 位 双精度 52 位

举例

17.625在内存中的存储

第一步:先将17.625转化为二进制表示:10001.101

第二步:再将10001.101右移,直到小数点前只剩1位:1.0001101 * 2^4(右移4位)

第三步: 确定符号位 :正 0 负 1

确定指数位:实际为4 但要加上127 所以为131 二进制为1000 0011

确定尾数:因为小数点前为1,所以IEEE规定值记录小数点后即可,

所以此处的底数为:0001101

综上 17.625在内存中的存储形式为:0100 0001 1000 1101 0000 0000 0000 0000

4、int bool float char 字符串 指针 和 零值比较(注意是与零值)

a、对于int if(0 == var) if( 0 != var)

b、对于bool bool零值为假 记为FALSE 任何非零值都是真 记为TRUE(注意:TRUE的值并没有统一 的标准,例如:VisualC++将TRUE记为1 而VisualBasic将TRUE定义为-1)所以不可以将bool变量直 接与TRUE、FALSE或者0、1进行比较 。正确方式:if(flag) if(!flag)

c、对于float(double)都有精度限制 都不可以使用== !=让浮点型和0值比较而应该转化为>=和<= 的形式。正确比较方式: #include<float.h> FLT_EPSILON DBL_EPSILON

if((x >= -FLT_EPSILON ) || (x <= FLT_EPSILON ))

d、对于char 跟int类似

e、对于char *(字符串)if(NULL == p) if(NULL != p)

f、对于指针:同e类似

进制关系

c语言中常用进制从 二 八 十 十六 相互转化

位运算 & | ! ^ << >>

补码:正数是自己本身 负数:符号位不变 其他位按位取反再加1

转义字符

换行 \n

tab \t

\\ 输出\

%% 输出%

\” 输出”

输入与输出

1、输入 printf

格式 printf("输出的内容 占位符[占位符2......]",变量);

%d:整型 %o:8进制 %x:16进制 %hd:短整型 %ld:长整型

%c:字符 %f:单精度 %lf :双精度%p:指针 %u:无符号

2、输入 scanf

格式 scanf("占位符[占位符2 占位符3]",&变量);

占位符和占位符之间如果是空格用空格连接 如果是逗号用逗号连接

运算符

1、算术运算符 + - / * %

2、赋值运算符 = (复合赋值运算符 *= /= -= += &=)

3、关系运算符 > < >= <= != ==

4、自增自减运算符

a++ 先取值 后++ 需要一个额外的辅助变量

++a 先计算 后取值 不需要额外的辅助变量

5、三目运算符

格式:表达式1?表达式2:表达式3

意义:如果表达式1为真,执行表达2,否则执行表达式3

6、运算符优先级

括号 > 单目 > 算术 > 移位 > 关系 > 逻辑 > 三目 > 赋值 > 逗号

分支语句

1、if语句

格式1:if(条件){} 格式2:if(条件){}else{}

格式3:if(条件){}else if(条件){} 格式4:if嵌套if(条件){if(条件)else{}}else{}

2、goto语句

格式 标志位:

goto 标志位

作用:跳转刀标志位处 进行标志位处往后的语句

3、switch case 开关语句

格式 switch(表达式[只可以是整型值]){ case 整型常量: 语句;break;case 整型常量: 语 句;break;default:语句;}

循环语句

1、while语句

a、格式 while(条件){循环体}

b、概念:当条件满足时,执行循环体,当不满足条件,跳出循环

break 退出整个循环,循环结束的标志

return 是程序结束的标志

continue 跳过当次循环

c、return与exit区别

  1. exit用于结束正在运行的整个程序,它将参数返回给OS,把控制权交给操作系统;而return 是退出当前函数,返回函数值,把控制权交给调用函数。

  2. exit是系统调用级别,它表示一个进程的结束;而return 是语言级别的,它表示调用堆栈的返回。

  3. 在main函数结束时,会隐式地调用exit函数,所以一般程序执行到main()结尾时,则结束主进程。exit将删除进程使用的内存空间,同时把错误信息返回给父进程。

  4. void exit(int status); 一般status为0,表示正常退出,非0表示非正常退出。

d、while嵌套循环

while(条件)

{

语句

while(条件)

{

语句

}

}

2、do while语句

格式 do{循环体}while()条件;

先执行一次循环,然后判断是否继续执行

3、for语句

a、格式 for(语句1;条件;语句2){循环体}

语句1为循环初值

条件1为继续循环(跳出循环)条件

语句2为自增自减语句

b、实例:求出3-100之间所有的素数

`#include<stdio.h> int main() { int x,y,z; for(x=3;x<=100;x++) { y=1; for(z=2;z<x;z++) { if(x%z==0) { y=0; break; } } if(y==1) { printf("%d是素数\n",x); } } return 0; }`

c、for嵌套循环

for()

{

语句

for()

{

语句

}

}

数组

1、一维数组

概念:相同数据类型数据的集合

格式: 数据类型 数组名[元素个数] = {数据1 ,数据2......}

int a[3] = {7,8,9};

元素:a[0]值为7

数组初始化

int abc[5]={1,2,3,4,5}   //全部初始化
int abc[5]={1,1,1}   //部分初始化        abc[4]=0
int abc[5]={0,0,0,0,0}  //初始化为0
int abc[]={1,2,3,4}   // 缺省初始化,会自动根据给出的元素的个数来决定[]中的数

注意:char arr[] = "abcd" 与char arr[] = {'a','b','c','d'}区别

2、二维数组

格式:数据类型 数组名[行][列] = {数据.....}

int arr[2][2] = {{1,2},{3,4}};

arr[0][0]值为1 arr[1][1] 值为4

初始化:

int arr[2][2]={1,2,3,4} //全部初始化 int arr[2][2]={1,2} //部分初始化 int arr[2][2]={ {1,2}, {3,4}} //分组初始化 int arr[][4]={1,2,3,4,5,6} // 缺省初始化

函数

1、概念:对一部分代码进行封装 方便使用 增加代码的模块化

2、格式:返回值类型 函数名(参数){函数体}

3、调用:直接写函数名

4、参数:调用者给被调用者传递的值

实际参数(实参):再内存中真实存在的

形式参数(形参):再函数调用前,没有实际的存储数值,只是一个形式,所有形参都是实参的拷贝

5、局部变量:定义再局部 ,是再括号中的变量

全局变量:定义再全局

6、变量的作用域和生命周期

作用域:变量可使用的范围

生命周期:变量再内存中存在到从内存中释放的时间

局部变量作用域:只再其定义的括号内使用

局部变量生命周期:从定义开始到括号结束

全局变量作用域:从定义开始带整个项目结束

全局变量生命周期:从定义开始到程序结束

7、当全局变量和局部变量重名时 ,优先使用局部变量

8、静态变量和常量

常量:不可修改的量 用const修饰

const int x = 10;

x = 9 ;//报错

静态变量:用static修饰 static int x

静态局部变量:生命周期发生改变(从定义开始到程序结束),作用域不发生变化

静态全局变量:生命周期不改变,作用域发生改变(仅在本文件中使用)

注意:静态局部变量只会被初始化一次

9、返回值

函数可以有多个返回值,但一次只有一个返回值

10、main函数参数 int main(int argc char *argv[])

参数 argc是参数个数 argv(指针数组)是参数内容

11、递归 : 自己调用自己 递归必须有出口

12、函数的可变长参数的使用

a、需要添加头文件:stdarg.h

b、格式:int add(int a,...);

c、va_list va_start va_arg va_end含义

va_list 类型:字符指针 typedef char *va_list 用于存储参数的地址

va_start宏原型:void va_start(va_list ap,last_arg)

其中last_arg是最后一个传递给函数的已知固定参数

与va_arg和va_end宏是一起使用的,并且要在其之前被调用

va_arg宏原型:type va_arg(va_list ap type)作用:从ap开始取一个type型的值返回,并且自动将 ap指向下一个参数

va_end宏原型:void va_end(va_list ap) 作用:将ap设置为NULL,如果在从函数返回之前没有 被调用va_end,则结果为定义

e、使用步骤

1.声明va_list变量

2.使用va_start指定可变长参数的位置

3.使用va_arg来获取参数值

4.可选,使用va_end将va_lisy清零

字符串

1、概念:用双引号引起来的,在代码里"abc" 最后还存在’\0‘ ’\0 ‘ASCII码是0

2、表示方法:char a[10] = {'a','b','v','d'};//部分初始化

char *arr = "abvded";

char arr[10] = "abcd";

3、字符串长度包括\0 ,但是有效长度不包含\0 %s打印字符串

4、常用字符串函数

a、比较 strcmp 作用:比较两个字符串是否相等 需要头文件string.h

函数原型:int strcmp(const char *s1,const char *s2)

参数:s1第一个字符串 s2第二个字符串

返回值:如果相同返回0 第一个比第二个大返回正数 第一个比第二个小返回负数(只比较第一处不同的地方)

b、计算长度 strlen 原型:int strlen(const char *s) 作用:计算字符串有效长度 不包含'\0'

c、拷贝字符串 strcpy 原型:char *strcpy(char *s1,const char *s2)

作用:将s2的内容拷贝到s1中

strncpy 原型 char *strncpy(char *dest,const char *s1,size_t n)

作用:拷贝s1中前n个字符 返回值:拷贝好的字符串 参数:dest目标 s1源字符串 n需要拷贝个数

d、字符(串)输入

char *fgets (p,sizeof(p),stdin);

char *gets(char *s);作用:输入一个字符串 以回车结束输入 参数:输入内容保存位置 返回值:输入内容

int getchar(void); 作用:输入一个字符 返回值:输入字符的ASCII码值

e、字符(串)的输出

int puts(const char *s);作用:输出一个字符串 参数:需要输出的内容 返回值:输出字符串字符个数包括\0

int putchar(int c);作用:输出一个字符 参数:需要输出字符的ASCII码值 返回值:输出字符的ASCII码值

f、字符串的追加 strcat 原型:char *strcat(char *s1,const char *s2);

作用:把s2字符串内容拼接到s1后面 返回值:拼接以后字符串的内容

5、sscanf 函数原型:int sscanf(const char *s,const char *format,...)

从s中读取数据,并根据参数格式将数据存储到附加参数的指定位置

sprintf 函数原型:int sprintf(char *str const char *format,...)

将数据写入字符串中,可以将多个元素合成一个字符串

6、atoi atol atoll int atoi(const char *str)把参数str所指向的字符串转换为一个整数;

7、memset 和 bzero

memset函数原型 void *memset(void *s ,int c,size_t n)

作用:将已经开辟内存空间s的首n个字节设置为c值 常用于内存空间的初始化

bzero函数原型:void bzero(void *s ,int n)

作用:将内存块(字符串)的前n个字节清零

bzero(void *ss,int n)与memset((void *) s,0,size_t n)等价

注意:bzero() 不是标准函数,没有在ANSI中定义,在VC6.0下编译不通过;Linux下的GCC支持

8、memcpy

memcpy函数原型:void *memcpy(void * destunation,const void * source,size_t num);

参数1:目的地址 参数2:源地址 参数3:要复制的字节数 返回值:目的地址

作用:复制内存块

9、memcmp

memcmp函数原型:int memcmp(const void *buf1,const void *buf2,unsigned int count)

作用:比较内存buf1和buf2前count个字节 buf1< buf2 返回负 大于返回正 等于返回0

10、memcpy与strcpy区别:

a、memcpy可以复制任何内容 如字符数组、整型、结构体 而strcpy只能复制字符串

b、复制方法不同 strcpy不需要指定长度 遇到\0结束 可能溢出 memcpy根据第三个参数决定复制长度

结构体

1、定义:不同数据类型的集合 属于自定义数据类型

2、格式: struct 结构体名{数据类型 变量1; 数据类型 变量2;......};

3、声明: struct 结构体名 变量名;

4、结构体大小的对齐和补齐

a、先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。

b、实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:

一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)

二、结构体大小必须是所有成员大小的整数倍

5、改名:typedef

共用体

1、概念:多个变量共用一个存储空间

2、关键字:typedef union 共用体名称{ 类型 变量1:类型 变量2;.....};

3、大小:由共用体中字节最大的类型来决定(同样遵循对齐原则)

4、存储:同一时间 只有一个变量存在 任意成员变量的改变都会影响数据

5、场景:发送端发送数据后不知道会接收什么样的数据,所以通过共用体来接收数据

6、大小端的存储:低地址存低位数据,高地址存高位数据 叫小端存储

低地址存高位数据,高地址存地位数据 叫大端存储

ARM的储存方式就是小端存储

7、写一个函数判断当前机器的存储模式

如果a = 1, 那么&a后的第一个字节不同(小端存储模式为1,大端存储模式为0),又知char* 类型 的指针在访问内存是权限是一个字字节,所以用char* 访问a后如果结果为1,则为小端存储模式,若结果为0,则为大端存储模式。

枚举类型

1、枚举:用一个名字替代一个值,为了代码可读性更好

2、格式:enum 枚举名{枚举常量1,枚举常量2}

3、使用 :把枚举常量当成值来用

4、枚举值:默认首个常量值为0,后面的常量自动加1,如果有赋值情况,就从被赋值的数开始,常量+1

5、大小:4个字节和int一样大

预处理指令

1.编译过程:预处理 ,编译,汇编,链接

2.预处理指令:以#为开头,不是C语言的语句,不需要加分号

包含:头文件,宏定义,条件编译

3.宏定义:用名字代替一个值

typedef 的区别:tepedef是编译阶段,而#define是预处理阶段

格式一:#define 宏名称 替换文本(值) 声明好的值不能被改变

格式二:#define 宏名称 (定义一个标志)

格式三:#define 宏函数(表达式)

注意:宏函数的参数自己没有括号,需要在每个参数上手动添加括号,因为宏函数只替换内容

4.条件编译

概念: 满足某个条件则编译某块代码,不满足不编译

格式一:

#ifdef 宏

编译代码1

#else

编译代码2

#endif

概念:如果宏存在,执行代码1,否则执行代码2

格式二 :

#if 条件

编译代码1

#else

编译代码2

#endif

概念:如果条件为真,执行代码1,否则执行代码2

格式三:

#ifndef 宏

编译代码1

#else

编译代码2

#end if

概念:如果宏不存在,执行代码1,否则执行代码2

头文件

作用:定义结构体,函数的声明,宏定义,文件

后缀:.h

使用:如果使用自定义头文件 需要用“”

因为<>是使用系统库头文件

区 别:<>默认先从库文件里开始查找,再从PATH文件查找,如果没找到就报错

“ ”默认从当前目录开始查找,再从库文件里开始查找,再从PATH文件查找,如果没找到就报错

指针 (基于64位系统)

指针在C语言运用广泛

1.所有数据都存在内存当中,每一个内存单元又称为一个字节,每个类型占不同字节数

指针:指向地址的变量,保存的是地址

地址:变量储存的位置,

2.定义指针

格式:数据类型 * 指针变量名 =&变量

int a=10

int *p=&a

*p=132

3.指针的运算

        算术运算:++,--;+常量;-常量;地址+地址

        +常量: p+n 指针向地址大的地方移动n个数据

        - - 小

        ++:p++或者++p 指针向地址大的地方移动一个数据

        -- : 小

        p-q: 两个同类型指针间隔数据的个数

4.空指针

        空指针:指向NULL的指针,当你不知道指针指向哪里时,赋值为NULL

        没有指针初始化,P的指向不确定

5.野指针

        概念:不固定指向某一位置的指针

6.void指针

        通用型指针:它的指针变量的数据类型不确定,那就可以保存任何类型的地址,但是必须进行强制类型转换

7.常指针

        概念:只有const挨着指针的时候才是修饰这个常指针,指针的指向不可以被改变

        指针常量:

        const int *p=&a;

        *p=22不行 a=22可以;

        常量指针:

        int * const p =&a;

        *p=22可以 a=22不可以

        补充:

                如果定义一个const变量,用指针指向这个变量后,通过解引用去修改

                const int a=123;

                int *p=&a;

                *p=222;允许

        指针对指针直接赋值

        int a=123;

        int p,q

        int *p=&a

        int *q=p

8.二级指针

        1.二级指针:指向一级指针变量的指针叫二级指针 保存的是一级指针的地址

                                一级指针中保存的是指向的变量的地址

        2.格式: 数据类型 **二级指针名=&一级指针的变量名

        例子:int a=123 int *p=&a int **pp=&p

动态内存分配

1.总共分为:代码区,数据区,堆区,栈区

        根据地址从小到大分布如下:

        代码区:存放代码的地方,不可以被修改

        数据区:静态量:静态变量和静态常量

        全局变量区:已经初始化过的全局变量

        bss段:未初始化的全局变量

        堆区:动态内存申请,自己申请自己释放,优先分配低地址,再给高地址

        栈区:存放局部变量,自己申请自己释放,优先分配高地址,再给低地址

2.动态内存申请

 void *malloc(size_t size)

 作用:在堆空间中申请内存

 参数:需要申请的内存大小

头文件:stdlib.h

返回值:申请到的内存空间的首地址

int *p=(int *)malloc(8)

注意:malloc的返回值需要进行强制类型转化

malloc申请的内存空间,要释放

void *calloc(size_t nmemb,size_t size)

作用:动态申请内存,申请的内存初始化为0

参数:nmemb 申请的内存块的个数

size 每块内存的大小

返回值:申请的内存空间的首地址

void *realloc(void*ptr,size_t size)

作用:申请内存空间

参数:从ptr地址开始申请 size 是申请的大小

返回值:申请 的内存空间的首地址

3.释放动态申请内存空间

void free(void*ptr)

作用:释放动态申请的内存空间,如果不释放,内存会泄露

参数:malloc 返回的指针

返回值:无

4、perror和errno以及stderr

stderr:标准错误//屏幕输出的错误信息会存储在这个文件里 与正常输出到stdout的信息分开

perror函数原型 void perror(const char *s)

作用:将上一个函数发生错误的原因输出到标准错误stderr中 s为用户提示信息会被点打印出来后面紧跟着错误原因的字符串,错误原因依照全局变量errno的值来决定要输出的字符串

errno:库函数中变量,每个errn值对应着以字符串表示的错误类型,当调用某些函数出错时,errno会被赋予对应的值,不同数值表示不同的出错原因

函数指针

1、概念:函数名就是函数的首地址,可以用指针存放,那么我们就把这个指针叫函数指针

2、格式:int (*p)(int,int) 函数返回类型 (指针变量名)(函数参数)

定义

int max(int *a,int *b)

{

if(a >b) return a;

else return b;

}

int (*p)(int *,int*);

使用

p = max;

(*p)(x,y);

回调函数

1、概念:通过函数指针调用函数 把函数的指针地址作为参数传递给另外一个函数当这个指针,当这个指针指向其他函数时,叫回调函数

2、格式 数据类型 函数名 参数(函数指针){}

数组与指针的关系

1、数组指针:是指针 指向某一个数组 形式:int (*p)[5];//五列 为二级指针

2、指针数组:是数组,数组里面都是指针 int *a[3];a[0] a[1] a[2] 均为地址

指针数组与一维数组关系

#include <stdio.h>

int main() { int * p[3]; int a[] = {3,6,1,9,10};

p[0] = a;
p[1] = a + 1;
p[2] = a + 3;
    //p[0],p[1],p[2]均为地址
printf("%d %d %d\n", a[0], a[1], a[3]);
printf("%d %d %d\n", *(p[0]), *(p[1]), *(p[2]));
    //[]的优先级高于* 所以()可以省略
return 0;

}

指针数组与二维数组的关系

#include <stdio.h>

int main() { int a[2][3] = {{1,4,6},{12,9,7}};

int * p[2];
​
p[0] = a[0];//&a[0][0]
p[1] = a[1];//&a[1][0]
​
printf("%d\n", a[0][1]);
printf("%d\n", *(a[0]+1));//加*取值
printf("%d\n", *(p[0]+1));//一级指针加1是移动一个数(列)
​
    printf("%d\n", *(p[1]+2));
  
return 0;

}

指针和结构体

1、定义结构体指针: 结构体名 *指针名 = &结构体变量名 struct student *p=&stu1;

2、结构体指针名指向成员变量名 如 :p->num

指针和字符串

char *s; s="hellow"; 

说明:如文章中有错误,请大家及时指出,共同学习,共同进步。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值