自学c语言
C 语言是一种通用的、面向过程式的计算机程序设计语言。
当前最新的 C 语言标准为 C18
前期准备
C 编译器 写在源文件中的源代码是人类可读的源。它需要"编译",转为机器语言,这样 CPU 可以按给定指令执行程序。(.c-->.exe)
下载Dev-C++ 图标长这样哦别下载错了
编写代码
- 1 #include <stdio.h>
- 2 int main(){
- 3 printf("Hello World!");
- 4 //system("pause"); //暂停程序 不会一闪而过
- 5 return 0;
- 6 }
保存为 hello.c 文件
进入代码目录
win+r cmd 打开命令提示符 cd到程序目录执行编译 gcc hello.c 会生成hello.exe 文件
想用vs code开发C语言点击这里
数据类型
1 基本类型:
它们是算术类型,包括两种类型:整数类型和浮点类型。
2 枚举类型:
它们也是算术类型,被用来定义在程序中只能赋予其一定的离散整数值的变量。
3 void 类型:
类型说明符 void 表明没有可用的值。
4 派生类型:
它们包括:指针类型、数组类型、结构类型、共用体类型和函数类型。
存储类
存储类定义 C 程序中变量/函数的可用范围和生命周期。说明符应放置类型之前
1.auto
局部变量的默认存储类, 规定变量只能在函数内部使用
2.register
定义存储在cpu寄存器中而不是 RAM(内存) 中的局部变量
3.static
局部变量时进入和离开作用域不会进行创建和销毁
全局变量时会使变量的作用域限制在声明它的文件内
4.extern
在一个文件中声明一个全局变量或函数
- #include <stdio.h>
- // 函数外定义变量 x 和 y
- int x;
- int y;
- int add(){
- // 函数内声明变量 x 和 y 为外部变量
- extern int x;
- extern int y;
- // 给外部变量(全局变量)x 和 y 赋值
- x = 4;
- y = 2;
- return x+y;
- }
- int main()
- {
- int result;
- result = add();
- //文件编码UTF8时中文乱码 应设为GBK
- printf("result 为:%d=%d+%d",result,x,y);
- return 0;
- }
运算符
7个 算术运算符 关系运算 符逻辑运算 符位运算符 赋值运算符 杂项运算符
- #include <stdio.h>
- //不用第三个变量 A^B,异或交换值
- // 这种利用位运算的交换方法只适用于整型变量,不能用于浮点型变量
- int main()
- {
- int A = 60;//二进制 0011 1100
- int B = 13;//二进制 0000 1101
- A = A^B;//A=0011 0001
- B = A^B;//B=0011 1100
- A = A^B;//A=0000 1101
- // A^=B^=A^=B; //简写
- printf("原A=60 B=13,现A=%d,B=%d",A,B);
- return 0;
- }
enum(枚举)
一种基本数据类型 enum 枚举名 {枚举元素1,枚举元素2,……};
第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。
可以把第一个枚举成员的值定义为 1,第二个就为 2,以此类推
- #include <stdio.h>
- #include <stdlib.h>
- // 枚举类型
- int main()
- {
- enum Colors { red=1, blue, green };
- enum Colors color;
- printf("%d是红色,%d是蓝色,%d是绿色,请输入数字选择喜欢的颜色",red,blue,green);
- scanf("%u",&color);
- switch(color){
- case red:
- printf("你喜欢红色\n");
- break;
- case blue:
- printf("你喜欢蓝色\n");
- break;
- case green:
- printf("你喜欢绿色\n");
- break;
- default:
- printf("没有你喜欢的颜色\n");
- }
- system("pause");
- }
C指针
指针指向内存地址的变量,指针变量存放的是普通变量的内存地址
- int var = 20; /* 实际变量的声明 */
- int *ip; /* 指针变量的声明 */
- ip = &var; /* 在指针变量中存储 var 的地址 */
*和&都是一元运算符
&var 返回的是变量var在内存中的地址
*ip 返回的是指向的变量var(20)的值
普通指针和数组指针:
- #include <stdio.h>
- // 指针 &a=获取变量地址 *a=指针变量
- int main()
- {
- int var = 12;
- int *ip = NULL;
- ip = &var;
- printf("var 变量地址:%p \n",&var);
- printf("ip 变量存储的地址:%p \n",ip);
- printf("ip 变量地址:%p \n",&ip);
- printf("*ip 变量的值:%d \n",*ip);
- system("pause");
- // int var = {
- // 地址:000000000062FE14
- // 值:12
- // }
- // &var = var地址
- // int *ip = {
- // 值:NULL
- // 地址:000000000062FE10
- // }
- // ip = &var
- // *ip = var值 = 12
- // ip = &var = var地址
- //指针与数组
- const int MAX = 3;
- int arr[] = {10,100,200};
- int i,*ptr[MAX];
- for(i=0;i<MAX;i++){
- ptr[i] = &arr[i];
- }
- for(i=0;i<MAX;i++){
- printf("var[%d] 地址:%p || %p,值:%d \n",i,ptr[i],&arr[i],*ptr[i]);
- }
- system("pause");
- return 0;
- }
函数指针:
- #include <stdio.h>
- // 函数指针
- int max(int x,int y){
- return x>y?x:y;
- }
- int main()
- {
- int (*p)(int,int) = &max; //&可以忽略
- int a,b,c,d;
- printf("请输入3个数字:");
- scanf("%d %d %d",&a,&b,&c);
- d = p(p(a,b),c);
- printf("最大数为:%d \n",d);
- system("pause");
- }
字符串
C 语言中,字符串实际上是使用空字符 \0 结尾的一维字符数组。\0 是用于标记字符串的结束
- #include <stdio.h>
- #include <string.h>
- // 字符串
- int main()
- {
- char arr[6] = {'h','e','l','l','o','\0'};
- printf("%s \n",arr);
- char str[] = "hello";
- printf("%s \n",str);
- char str1[] = "字符串1",str2[] = "字符串2",str3[5];
- // 操作字符串的函数 需要引入<string.h>标准库
- strcpy(str3,str1);//将str1复制到str3
- printf("str3=%s \n",str3);
- strcat(str3,str2);//将字符串str2链接到str3末尾
- printf("str3=%s \n",str3);
- int len = strlen(str3);//返回str3的长度
- printf("str3的长度为%d \n",len);
- int cmp = strcmp(str3,str1);//如果 str1,str3相同的,返回 0;str1<str3 返回小于 0;str1>str3 返回大于 0。
- printf("cmp=%d \n",cmp);
- char *chr,ch='1';//ch为一个字符
- // str3="字符串1字符串2"
- chr = strchr(str3,ch);//返回一个指针 字符ch 第一次出现的位置
- printf("chr=%s \n",chr);//返回 "1字符串2"
- char s[2] = "串";//汉字一般占2个字节(系统或编码方式不一样可能占3个字节)
- char *ss = strstr(str3,s);//返回一个指针,指向字符串 str3字符串 s 的第一次出现的位置
- printf("\'串\'出现在str3的位置为:%s \n",ss);
- system("pause");
- }
结构体
用struct定义,自定义数据类型用来存储不同类型的数据成员
- struct 结构名 {
- 数据类型1;
- 数据类型2;
- ...
- } 变量1,变量2 ... ;
结构体变量的初始化,访问结构成员,结构作为函数参数,指向结构的指针 例子:
- #include <stdio.h>
- #include <string.h>
- // 结构体
- struct Books//生成结构体Books
- {
- char title[50];
- char author[50];
- char subject[50];
- int book_id;
- } book;//声明结构变量book
- void printBook(struct Books book);
- void setBook(struct Books *b,char title[],char author[],char subject[],int book_id);
- int main()
- {
- //初始化book变量
- strcpy(book.title,"百科全书");
- strcpy(book.author,"小明");
- strcpy(book.subject,"啥东西都有");
- book.book_id = 1;
- struct Books book1;//声明结构变量 book1
- setBook(&book1,"十万个为啥","小红","啥东西都有解释",2);
- printBook(book);
- printf("\n");
- printBook(book1);
- system("pause");
- }
- //通过指向结构变量的指针 "->"访问并初始化结构变量
- void setBook(struct Books *b,char title[],char author[],char subject[],int book_id)
- {
- strcpy(b->title,title);
- strcpy(b->author,author);
- strcpy(b->subject,subject);
- b->book_id = book_id;
- }
- //结构作为参数
- void printBook(struct Books book)
- {
- printf("标题:%s \n",book.title);//book.title 访问结构成员
- printf("作者:%s \n",book.author);
- printf("主题:%s \n",book.subject);
- printf("ID:%d \n",book.book_id);
- }
共用体
可以在相同的内存位置定义个带有多成员的共用体,只能有一个成员带有值
- union 共用体名 {
- 数据类型1;
- 数据类型2;
- ...
- } 变量1,变量2 ... ;
使用例子:
- #include <stdio.h>
- #include <string.h>
- //共用体
- int main()
- {
- // 声明共用体
- union Data{
- int i;
- float f;
- char c[10];
- };
- // 定义共用体 变量
- union Data data;
- // 初始化共用体 数据成员
- data.i = 123;
- printf("i:%d \n",data.i);//正常输出 123
- data.f = 20.3;
- printf("f:%f \n",data.f);//正常输出 20.299999
- strcpy(data.c,"1234567890");
- printf("c[10]:%s \n",data.c);//正常输出1234567890
- // 访问共用体数据成员
- printf("\ni:%d \n",data.i);//i内存位置被c[10]替换输出数据有问题 875770417
- printf("f:%f \n",data.f);//f内存位置被c[10]替换输出数据有问题 0.000000
- printf("c[10]:%s \n",data.c);//内存位置被替换为 正常输出1234567890
- system("pause");
- }
位域
1000 1000 这是8位(bit) = 1字节(byte/B)
有些信息存储时,不需要占一个完整的字节(8位),而只需占几个或1个二进制位(如:0000 0001 只需要最后1位)
所以c语言提供了一种数据结构,称为"位域"或"位段,可以设置变量用多少位
- struct 位域结构名
- {
- //type 只能为int(整型),unsigned int(无符号整型),signed int(有符号整型) 三种类型
- type [member_name] : width ;
- type [member_name] : width ;
- ...
- };
这种结构在内存中占8个字节
但是我们a和b可能只存储 0或1 只需要1位,多余的空间就会浪费。 所以就需要用到位域
使用位域后,这个结构体就占用4字节(32位)。每个变量占1位 ,还剩余30位,可以分配给剩余结构体中变量
- #include <stdio.h>
- // 位域
- int main()
- {
- // unsigned int类型默认是2字节或4字节
- struct
- {
- unsigned int a:1;
- unsigned int b:1;
- } status;
- struct
- {
- unsigned int a;
- unsigned int b;
- } status1;
- printf("status size:%dB \n",sizeof(status));//status size:4B
- printf("status1 size:%dB \n",sizeof(status1));//status size:8B
- // status.a = 2;//因为a只分配了1位 2等于二进制0010 所以会报错
- status.a = 1;//1等于二进制0001
- printf("status.a:%d \n",status.a);
- system("pause");
- }
typedef 和 #define
typedef:为类型取一个新的名字
#define:为各种数据类型定义别名
不同点
- typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
- typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。
- #include <stdio.h>
- // typedef 关键字为类型取一个新的名字
- int main()
- {
- typedef unsigned int BYTE;//定义unsigned int别名为 BYTE
- BYTE A;
- unsigned int a;
- #define zx int //定义int别名为zx
- #define PI 3.14 //定义常量
- zx b;
- A = 2;
- a = A;
- b = a;
- printf("%d == %d \n",A,a);
- printf("%d,PI=%f\n",b,PI);
- system("pause");
- }
输入输出
C 语言把所有的设备都当作文件。所以设备(比如显示器)被处理的方式与文件相同。
- #include <stdio.h>
- // 输入输出
- int main()
- {
- int a;
- char s[50];
- // printf("Enter a value:");
- // scanf("%s",&s);//输入 从标准输入流 stdin 读取输入
- // printf("value = %s \n",s);//输出 写入到标准输出流 stdout
- printf("Enter a char:");
- a = getchar();//屏幕读取下一个可用的字符,并把它返回为一个整数
- printf("you entered char:\n");
- putchar(a);//把字符输出到屏幕上,并返回相同的字符。
- printf("\n");
- // char str[100];
- // printf("Enter a string: \n");
- // gets(str);//从 stdin 读取一行到 s 所指向的缓冲区,直到一个终止符或 EOF
- // printf( "\nYou entered: ");
- // puts(str);//字符串 s 和一个尾随的换行符写入到 stdout
- system("pause");
- }
文件读写
不管是文本文件还是二进制文件,都是代表了一系列的字节。
打开文件 FILE *fopen( const char * filename, const char * mode );
filename 是字符串,文件名, mode 是下列值中的一个
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
处理二进制文件:
- "rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"
- #include <stdio.h>
- //文件的读写
- int main()
- {
- FILE *fp = NULL;
- // 写入文件
- fp = fopen("./13.txt","w");// "w" 打开一个文本文件,允许写入文件。如果文件不存在会创建一个新文件
- fputc(2,fp); //把一个字符写入到流中
- fprintf(fp,"这是 创建的文件\n"); //把一个字符串写入到文件中
- fputs("这是 fputs 输入的内容\n",fp); //把字符串 s 写入到 fp 所指向的输出流中 成功返回一个非负值,发生错误,返回 EOF
- fclose(fp);//关闭文件
- char buff[255];
- // 读取文件
- fp = fopen("./13.txt","r");//打开一个已有的文本文件,允许读取文件
- char c = fgetc((FILE *)fp);//从 fp 所指向的输入文件中读取一个字符
- printf("0:%d \n",c);
- fscanf(fp,"%s",buff);//读取字符串,但是在遇到第一个空格和换行符时,它会停止读取
- printf("1:%s \n",buff);
- fgets(buff,255,(FILE *)fp);//从 fp 所指向的输入流中读取 n - 1 个字符
- printf("2:%s \n",buff);
- fgets(buff,255,(FILE *)fp);
- printf("3:%s \n",buff);
- // 0:2
- // 1:这是
- // 2: 创建的文件
- // 3:这是 fputs 输入的内容
- fclose(fp);
- return 0;
- }
预处理器
相当于文本替换工具,会在编译器实际编译之前执行
14.c
- #include <stdio.h>
- // 预处理器
- #include "14.h" //包含一个源代码文件
- int main()
- {
- //定义宏
- #define PI 3.14 //把所有 PI 替换成3.14
- #define uInt unsigned int //把所有 uInt 替换成 unsigned int
- uInt a = 222;
- #undef PI //取消已定义的宏
- #define PI 3.1415926 //重新定义PI
- printf("%f,%d \n",PI,a);
- myFun();
- #ifndef MESSAGE //如果宏没有定义,则返回真
- #define MESSAGE "success"
- #endif
- printf("MESSAGE = %s \n",MESSAGE);
- return 0;
- }
- void myFun()
- {
- printf("This is 14.h a=%d,arr=%s \n",a,arr);
- }
14.h
- int a = 4;
- char arr[] = "hello word";
- void myFun();
头文件
头文件是扩展名为 .h 的文件,包含了函数声明,宏定义,变量。被多个源文件中引用共享。有两种类型的头文件:程序员编写的,编译器自带。
- #include <file.h>
- #include "file.h"
强制类型转换
强制类型转换是把变量从一种类型转换为另一种数据类型
- #include <stdio.h>
- // 强制类型转换
- int main()
- {
- int a = 6;
- char b = 'b';
- float c = a + b;//a 强制转换为 6.000000 b 强制转换为 98('b'的ASCII=98)
- printf("a=%d+b=%c,c=%f \n",a,b,c);
- system("pause");
- }
内存管理
C分配和管理函数。这些函数在 <stdlib.h>头文件
- void *calloc(int num, int size);//分配了 num*size 个字节长度的内存,每个字节值都初始化为0
- void free(void *address);//释放 address 所指动态分配的内存空间
- void *malloc(int num);//堆区分配指定大小的内存空间,不会初始化值
- void *realloc(void *address, int newsize);//内存扩展到 newsize
使用malloc分配内存
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- int main()
- {
- char name[100];
- char *desc;
- strcpy(name,"weilian tom");
- desc = (char *)malloc(200 * sizeof(char));//动态分配内存 它的值不会初始化
- printf("%p \n",desc);
- if(desc == NULL){
- fprintf(stderr,"Error - unable to allocate required memory\n");
- }else{
- strcpy(desc,"weilian tom is a famous professional clown actor \n");
- }
- // free(desc);//释放内存
- printf("name:%s\ndesc:%s \n",name,desc);
- system("pause");
- }
命令行参数
执行程序时,在命令行传值给程序
传入的参数是由main函数处理的,argc是参数个数 argv是参数列表
- #include <stdio.h>
- // 命令行参数
- int main(int argc, char *argv[])
- {
- printf("有%d个参数 \n",argc);
- int i;
- for(i=0;i<argc;i++)
- {
- printf("第%d个参数是:%s \n",i+1,argv[i]);
- }
- }
执行程序后 第一个参数总是程序名
时间格式化和定时器函数
- #include <stdio.h>
- #include <time.h>
- // 标准库 time.h
- void delayed(void (*fun)());
- void parseTime();
- int main()
- {
- //time_t这是一个适合存储日历时间类型
- time_t curtime;//声明time_t格式变量
- printf("%d",curtime);
- time(&curtime);//计算当前日历时间,并把它编码成 time_t 格式
- printf("%s",ctime(&curtime));//ctime 返回表示当地时间的字符串
- delayed(&parseTime);
- return 0;
- }
- // 获取当前时间并格式化
- void parseTime(){
- time_t ct;
- time(&ct);
- // 格式化时间
- struct tm *nowTime = localtime(&ct);// 返回本地时区的值来填充 tm 结构体
- //年tm_year 月tm_mon 日tm_mday 时tm_hour 分tm_min 秒tm_sec
- printf("%d-%d-%d %d:%d:%d \n",nowTime->tm_year+1900,nowTime->tm_mon+1,nowTime->tm_mday,nowTime->tm_hour,nowTime->tm_min,nowTime->tm_sec);
- }
- // 延时函数
- void delayed(void (*fun)()){
- while (1)
- {
- static int t1,t2;
- if(t2-t1 > 1000){
- fun();
- t1 = t2;
- }
- t2 = clock();//返回程序执行起到现在使用的时间
- }
- }
搜索
复制
自学c语言的更多相关文章
- 关于自学C语言开始时应该注意的问题分享—未完待续......
---恢复内容开始--- 自学C语言编程总结 第1章C语言概述 1. 如果用户将主函数的返回值类型定义为了void,则不需要返回任何值: 2. C语言的基本结构包括主函数和程序体两部分 ...
- 先定一个小目标:10天自学C语言编程,教你如何改变一生
C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...
- 关于自学C语言这件事
说在前面 为什么会写下这篇文章?本人也并不是什么大神,但是也自学了很久,从一个小白开始自学,期间走过很多弯路,掉过许多坑.一路跌跌撞撞下来,算是有了点收获,有了点感想,将它们记录下来,希望能帮助新入坑 ...
- 《自学C语言》初级教程 - 目录
我现在打算出一个C语言学习教程,目的是为了让初学者能够很容易和更深刻地理解C语言. 你可能有这样的疑问,网上不是有很多的初级教程吗,我需要这个吗?我的回答是:网上的C语言教程讲得不够全面,而且许多的初 ...
- 《自学C语言》第一章:C语言简介
这一章主要介绍什么是C语言,以及它的产生.发展历史.如其中所说的计算机术语有不懂的请百度,例如什么是强类型,什么是高级语言. 1.C语言是什么? 答:C语言是一门通用计算机编程语言,应用广泛.C语言的 ...
- 自学SQL语言的例子(使用MySQL实现)
SQL语言作为一种数据库管理的标准语言有着极为广泛的应用场景,菜鸟入门选用的数据库软件是轻量级的免费(这个极为重要)的MySQL,下载链接如下:http://www.mysql.com/downloa ...
- 2018.08.31 19:41 自学go语言
有的人是从最基础的开始学,而我却是从最简单开始学,学着调试,学着编程,其实我也是编程小白,好多的不懂,我不明白很多都可以用云完成了,为什么还要继续自己编程,不明白,但是有需求吧,有需求是件好事情,说明 ...
- (转)如何学好C语言,一个成功人士的心得!
zidier111发表于 2013-1-26 08:59:05 今 天,我能够自称是一个混IT的人,并能以此谋生,将来大家能一次谋生,都要感谢两个人:克劳德.香农和约翰.冯.诺依曼,是他们发现了所 ...
- 怎样学好C语言,一个成功人士的心得!
今天,我能够自称是一个混IT的人,并能以此谋生,将来大家能一次谋生,都要感谢两个人:克劳德.香农和约翰.冯.诺依曼,是他们发现了全部的数字化信息,不论是一段程序,一封email,一部电影都是用一连串的 ...
随机推荐
- Numpy怎样将数组读写到文件
Numpy怎样将数组读写到文件 本文档介绍的是Numpy以自己内建二进制的方式,将数组写出到文件,以及从文件加载数组: 如果是文本.表格类数据,一般使用pandas这个类库做加载和处理,不用numpy ...
- printf()函数压栈a++与++a的输出
printf()中a++与++a的输出问题 在C语言中有个很常用的函数printf(),使用时从右向左压栈,也就是说在printf("%d %d %d %d\n",a,a++,++ ...
- CSS: 给表格的第一列和最后一列不同的样式
table td:first-child { width:160px; height:20px; border:solid 1px Black; padding:5px; text-align:cen ...
- 什么是RESTFUL?REST的请求方法有哪些,有什么区别?
这里是修真院前端小课堂,每篇分享文从 [背景介绍][知识剖析][常见问题][解决方案][编码实战][扩展思考][更多讨论][参考文献] 八个方面深度解析前端知识/技能,本篇分享的是: [什么是REST ...
- VasSonic Android源码解析
VasSonic是腾讯推出的为了提高H5页面首屏加载速度而推出的高性能Hybrid框架,目前广泛应用在QQ商城等Hybrid界面中,以提高用户体验. https://github.com/Tencen ...
- zx-editor 移动端(HTML5)富文本编辑器,可与原生App混合(hybrid)开发
ZxEditor 移动端HTML文档(富文本)编辑器,支持图文混排.引用.大标题.无序列表,字体颜色.加粗.斜体. 可用于独立web项目开发,也可以用于与原生App混合(hybrid)开发. 源码地址 ...
- 圆桌killer
[问题描述] 圆桌上围坐着2n个人.其中n个人是好人,另外n个人是坏人.如果从第m(m<=2n)个人开始数数,数到第k个人,则立即处死该人:然后从被处死的人之后重新开始数数,再将数到的第k个人处 ...
- 集成JUnit测试
集成JUnit测试 既然使用了Spring,那么怎么集成到JUnit中进行测试呢,首先大家能够想到的肯定是: public class TestMain { @Test public void tes ...
- kubectl get node -n wide --show-labels
集群环境:1.k8s用的是二进制方式安装2.操作系统是linux (centos)3.操作系统版本为 7.4/7.94.k8s的应用管理.node管理.pod管理等用rancher.k8s令牌以及ma ...
- linux添加磁盘及分区挂载
磁盘管理 1.为什么要添加磁盘 随着系统的使用,磁盘的内容会越来越少,所以这时要添加磁盘增加空间 Linux系统中磁盘管理就是将硬盘通过挂载的方式挂载到linux文件系统中. 2.系统添加磁盘并分区 ...