C语言能不能进阶

运算符

单目运算 sizeof

1、数据类型/数组变量/指针: 返回所占用的内存字节数
sizeof(int);// 占4字节内存,根据编译器的版本决定
char a[] = “abc”;//sizeof(a)=4,字符串末尾还存在一个NULL终止符。
int a[50]; //sizeof(a)=4*50=200; 求数组所占的空间大小
int *a=new int[50];// sizeof(a)=4; a为一个指针,
   

算术运算符功能优先级
++自增2
自减2
*、/乘除3
%求余/取模3
+、-加减4
赋值运算符功能优先级
=赋值14
+=加后赋值14
-=减后赋值14
*=乘后赋值14
/=除后赋值14
%=取模后赋值14
关系运算符功能优先级
>大于6
<小于6
>=大于或等于6
<=小于或等于6
!=不等于7
==相等7
逻辑运算符功能优先级
逻辑非2
&&逻辑与11
||逻辑或12
位操作运算符功能优先级
&按位与8
|按位或10
~按位非2
^按位异或9
>>右移(M>>N等于 M/2 的N次方)5
<<左移(M<<N等于 M*2 的N次方)5

数据类型

在这里插入图片描述

1 基本类型

整型变量|整型变量符|所占空间|
short|短整型|2Byte(16Bit)
int|整型|4Byte(32Bit)
long|长整型|4Byte(32Bit)
unsigned short |无符号短整型|2Byte(16Bit)
unsigned int|无符号整型|4Byte(32Bit)
unsigned long|无符号长整型|4Byte(32Bit)

实型变量|实型变量符|所占空间|
float|单精度|4Byte(32Bit)
double|双精度|8Byte(64Bit)
long double|长双精度|16Byte(128Bit)

字符变量|字符变量符|所占空间 |
char |字符|  1Byte(8Bit)

整型常量|实例|
八进制整型常量|012
十进制整型常量|12
十六进制整型常量|0x12
长整型常量|12L

实型常量|实型常量符|
小数形式|-12.52.5
指数形式|2.5E52.5*105次方)

转义字符|含义 
\n |换行
\b|退格
\r|回车

1.1 字符串处理函数

函数含义
char *strcpy(char *dest, const char *src)字符串复制函数
int strcmp(const char *str1, const char *str2)字符串比较函数
size_t strlen(const char *str)字符串长度测量函数
char *strcat(char *dest, const char *src)字符串连接函数
char *strstr(const char *haystack, const char *needle)字符串查找函数
char *strchr(const char *str, int c)字符查找函数
void *memset(void *str, int c, size_t n)字符复制函数
  • strcpy(字符串复制函数)

作用是将 str2 复制到 str1 中去。

str1 的长度不能小于 str2 的长度 str1 必须为字符数组的形式、str2 可以为 字符串常量 和 字符组名

  • strcmp(字符串比较函数)

因为字符串不能用等号来比较大小,所以就用 strcmp 函数来比较 比较 ASCLL码

比较的结果由函数值带回:

(1)如果字符串1与字符串2相同,则函数值返回为0。

(2)如果字符串1 > 字符串2,则函数值返回一个正整数。

(3)如果字符串1 < 字符串2,则函数值返回一个负整数。

  • strlen(字符串长度测量函数)

返回字符串 s1 的长度。(不包括 ‘\0’ 在内)

  • strcat(字符串连接函数)

作用是把两个字符数组中的字符串连接起来,把字符串2连接到字符串1的后面,结果放在字符数组1中

  • strstr (字符串查找函数)

函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址(指针);否则,返回NULL。

  • strchr(字符查找函数)

返回一个指针,该函数返回在字符串 str 中第一次出现字符 c 的位置,如果未找到该字符则返回 NULL。

  • memset

复制字符 c 到str 的前n项,字符c 为 字符类型 acsll码

注意,如果字符 c 为 字符NULL ,十进制为 0的情况,此时的字符数组str必须要首地址才能重新赋值

2 构造类型

2.1 结构体:struct

结构体(struct)是具有相同类型不同类型的数据构成的数据集合。

结构体的声明并不会分配内存空间,构造类型定义变量时才会为其相应的变量分配内存空间

2.2 共用体:union

  • 结构体与共用体的区别

结构体

结构体大小是 结构体内部的成员的空间大小之和

共用体

共用体内存长度是内部最长的数据类型的长度。
共用体的地址和内部各成员变量的地址都是同一个地址

2.3 数组

将数组名传入函数时, 该数组名称则再也不是数组的首地址, 会成为普通的指针

sizeof(arr)/sizeof(arr[0])  
当前定义的函数内可以使用,传递后则不能使用

3 指针类型

3.1 函数指针、指针函数

指针函数,即本质是一个函数,函数返回类型是指针。
函数指针,即本质是一个指针变量,是指向函数地址的指针变量。

内存操作

1 静态存储区、栈、堆

在C语言程序中,能够获取的内存就是三种情况:栈(stack)、堆(heap)、静态存储区

在这里插入图片描述
在这里插入图片描述

  • 静态存储区

由 操作系统 分配 和 使用,有 .bss段 和 .data段组成,可读可写。

.data段(数据段)

已初始化的全局变量、静态变量存放在.data段。
.data段占用可执行文件空间,其内容有程序初始化。

.bss段
未初始化的全局变量、静态变量 和 初始化为0的全局变量、静态变量存放在.bss段。
.bss段不占用可执行文件空间,其内容由操作系统初始化。

  • 栈 stack

函数执行时,函数的形参以及函数内的局部变量,分配在栈区,函数运行结束后,形参和局部变量去栈(自动释放)。
编译器在需要的时候分配,不需要时自动清除

2 数据修饰 auto、static、register、const、volatile

  • auto

auto关键字 修饰局部变量

auto修饰局部变量,标志这个局部变量是自动局部变量,自动局部变量分配在栈上。(也就是说如果不初始化,那么值就是随机的)

auto的局部变量就是默认定义的普通的局部变量,省略了auto关键字而已,

  • static
static关键字可以修饰:局部变量、全局变量、函数
static修饰后改变了什么?
1.改变了生存周期 
2.改变了作用域 

static修饰不同对象时的作用:

1、局部变量:
局部变量就是在函数内定义的变量,普通的局部变量,生存周期是随着函数的结束而结束,
当用static修饰后,静态局部变量的生存周期就是当程序结束才会结束。
改变其生存周期的原因是被static修饰的局部变量被存放在.bss段或者.data段,而普通的局部变量是存放在栈上的。
总结:改变了生存周期,但是没有改变其作用域。

2、全局变量:
全局变量用static修饰改变了作用域,没有改变生存周期。
普通的全局变量是可以被其他的.c文件引用的,静态全局变量就只能被定义该全局变量的.c文件引用。
这样其他的文件就不能通过extern的方式去访问,这样主要是为了数据安全。
总结:改变其作用域,没有改变生存周期。

3、函数:
函数用static修饰,改变了作用域。
和静态全局变量一致

  • register

register修饰的变量(一般是全局变量),编译器会尽量将它分配在寄存器中。(平时分配的一般是在内存中的)。
通过改善这个变量的访问效率可以极大地提升运行效率。读写效率会更高。
所以register修饰的变量用在那种变量被反复高频率的作用,

  • const

const限定一个变量不允许被改变,产生静态作用。

可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。

  • volatile

volatile 关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问

3 动态内存管理(堆区 heap) malloc、calloc、realloc、free

开辟内存的函数 

1void* malloc(size_t size); 
 如果开辟成功,返回一个指向开辟好空间的指针。
 如果开辟失败,则返回一个NULL指针,所以使用malloc,要对返回值进行检查。 

2void* calloc(size_t num,size_ size);
 函数的功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0。
 与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全03、realloc 
 原本申请的空间不够,通过这个函数创建新的空间

释放动态开辟的内存

void free(void* ptr); 

4 GCC对C的扩展:内存对齐 attribute、aligned()、packed()

GNU使用__attribute__选项来设置我们想要的内存字节对齐大小。__attribute__选项不属于标准C语言,它是GCC对C语言的一个扩展用法。

GCC支持用__attribute__为变量、类型、函数、标签制定特殊属性。

大致有六个参数值可以被设定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias 。

  • aligned

该属性设定一个指定大小的对齐格式(以字节 为单位)

struct p
 {
  int a;
  char b;
  short c;
 }__attribute__((aligned(4))) pp;

sizeof(a)+sizeof(b)+sizeof(c)=4+1+1=6<8 所以sizeof(pp)=8

struct m
 {
  char a;
  int b;
  short c;
 }__attribute__((aligned(4))) mm;

sizeof(a)+sizeof(b)+sizeof(c)=1+4+2=7

a 后面需要用 3 个字节填充 才能和 b 是 4 个字节 一致 
所以 a 占用 4 字节, b 占用 4 个字节,而 c 又要占用 4 个字节。所以 sizeof(mm)=12

文件操作

1 文件 I/O 库

文件 I/O 指的是对文件的输入 / 输出操作,说白了就是对文件的读写操作
文件 I/O 是系统调用

1.1 文件描述符

文件描述符:是一个非负整数,是一个文件句柄,是与对应的文件绑定

文件描述符的分配:为没有被使用的且最小的非负整数

系统定义的文件描述符:0 1 2( 标准输入、标准输出、标准错位 )

1.2 读写操作(open 、close 、write 、read)

1open("路径""flag方式")
   open("路径""flag方式""权限")

flag方式

O_RDONLY:  只读方式
O_WRONLY:  只写方式
O_RDWR:    可读可写方式
O_CREAT:   不存在就创建
O_EXCL:    和 O_CREAT 搭配使用

权限

如果使用 O_CREAT,则需要加入第三个参数,设置文件的权限
 
2、close(文件描述符) 

3、write(文件描述符,"写入的数据""数据大小"4、read(文件描述符,"存储读取数据的缓冲区""数据大小"

1.3 文件 I/O 内核缓冲

调用 write() 只是将 字节数据拷贝到了 内核空间的缓冲区 ,拷贝完成之后函数就返回了, 在后面的某个时刻,内核会将其缓冲区中的数据写入(刷新)到磁盘设备中,所以由此可知,系统调用 write() 与磁盘操作并不是同步的,write()函数并不会等待数据真正写入到磁盘之后再返回。

  • 控制文件 I/O 内核缓冲的系统调用
1fsync()函数  文件的内容数据和元数据写入磁盘,只有在对磁盘设备的写入操作完成之后,fsync()函数才会返回

2fdatasync()函数 并不包括文件的元数据	

3sync()函数 将所有文件 I/O 内核缓冲区中的文件内容数据和元数据全部更新到磁盘设备中

2 标准I/O 库

标准C库中,用于文件I/O操作的库函数,叫做 标准I/O库

在这里插入图片描述

2.1 FILE 指针

FILE 指针的作用相当于文件描述符,只不过 FILE 指针用于标准 I/O 库函数中、而文件描述符则用于文件I/O 系统调用中

2.2 读写操作(fopen 、fclose 、fwrite 、fread)
  • fopen()
1fopen("路径""flag方式")

r  只读方式打开   O_RDONLY
r+ 可读可写方式   O_RDWR
w  只写方式打开(无文件则创建)  
w+ 可读可写方式打开(无文件则创建)
a  只写方式打开(在文件尾写入,无文件则创建)  
a+ 可读可写方式打开(在文件尾写入,无文件则创建)
 
2、fclose(FILE 指针) 

3、fwrite(”写入数据“,每个字节大小,总大小,FILE 指针)
  返回读取到的数据项的数目

4、fread(读出存储的数据缓冲区,单字节大小,总字节大小,FILE 指针)
  返回写入的数据项的数目

5、fseek(FILE 指针,偏移量,SEEK_SET)
  SEEK_SET 文件开头处
  SEEK_END 文件末尾处

2.3 标准 I/O 的 stdio 缓冲

标准 I/O 在应用层维护了自己的缓冲,称为stdio 缓冲

  • 控制 stdio 缓冲
1setvbuf(FILE 指针,buf,缓冲类型,大小) 
int setvbuf(FILE *stream, char *buf, int mode, size_t size);

缓冲类型:
_IONBF 无缓冲,将立即调用文件 I/O 操作 write()或者 read()

_IOLBF 行缓冲,遇到换行符"\n"时,标准 I/O 才会执行文件
       标准输入和标准输出默认采用的就是行缓冲模式 

_IOFBF 全缓冲 在填满 stdio 缓冲区后才进行文件 I/O 操作(read、write)。
       普通磁盘上的常规文件默认全缓冲模式。

2fflush(stdout)
	强制刷新将输出到 stdio 缓冲区中的数据写入到内核缓冲区
	

不常见的函数

终止进程 exit()、_exit()

这个参数用来表示进程终止时的状态,0表示正常终止,其余 表示非正常终止,

1void exit(int status)
exit()是C语言库函数 头文件 <stdlib.h>

2void _exit(int status)
 _exit()**系统调用函数**

在这里插入图片描述

  • exit()、return()的区别

exit()是一个库函数, return()是C语言的语句
exit() 函数最终会进入到内核,把控制权交给为内核,最终由内核去终止进程。
return并不会进入到内核,它只是一个main函数返回,返回到它的上层调用把控制权交给他的上层调用,最终由上层调用终止进程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值