C语言学习笔记(3)
在学习前,需要有一定的C语言基础。不必很深入,只需要知道函数,头文件,指针,数组等的概念就可以,但并非0基础笔记。
由于写到后面,不好编辑了,决定分成多篇写,请按编号学习,或者直接看目录先。
说明:该文章来自本人学习时的笔记,使用的编译器是Visual Studio,如有错误,可以在评论区或者私信我纠正,谢谢
15.命令行参数
15.1命令行参数实例
操作系统会传递一个命令行参数给main函数
main函数会返回一个状态码给操作系统,返回0成功,返回非0失败
在电脑里面,文件是用命令行来执行的,但是现在大部分都是使用鼠标点击的方式,让系统程序或者编译器程序自动化输入指令到命令行来调用exe文件执行
int main(int argc, char* argv[]) {
//argc:argument count,表示命令行参数的个数
//argv:argument vector,表示命令行参数,命令行参数的格式都是字符串
printf("argc = %d\n", argc);
for (int i = 0; i < argc; i++) {
puts(argv[i]);
}
return 0;
}
通过编译器,点击执行,执行上面代码以后会 出现下面的结果
直接进入当前文件路径,通过指令的方式,输入 命令行.exe,传递的参数就变成了 命令行.exe 了
命令行以空格为间隔计算一个参数,如此操作就变成了4个参数
15.2命令行参数存储逻辑
命令行参数的逻辑上存储如下图
15.3命令行参数与stdin读取数据的区别
命令行参数是在程序为执行的时候读取的
stdin读取数据是在程序已经运行以后读取的
15.4命令行参数的转换
提示: 如果命令行参数少于3个下面的代码会报错
int main(int argc, char* argv[]) {
int n;
float f;
sscanf(argv[1],"%d",&n);//读取argv[1]转化为整型读入到n中
sscanf(argv[2],"%f",&f);
return 0;
}
16.结构体struct
16.1 基本概念
结构体里面的元素叫成员
c语言的结构体只有属性,没有方法,C++的类和结构体有类也有方法。
//结构体的定义
struct student {//struct student是结构体的标签
int id;
char name[25];
char sex[10];
};
int main(){
//结构体的声明并初始化
struct student stu1 = {1,"小明","男" } ;
//和C++不同的是,c语言的结构体前面必须加struct,没学过c++的就按这个写就行
return 0;
}
16.2 结构体的内存结构
结构体的内存都是按边界对齐存储的如下图即上面的存储,一般按半字或者一字边界对齐存储,建议学习计算机组成原理内存部分加强理解
在使用结构体作为参数的时候,往往都是使用指针去作为参数防止大量复制
使用是,可以通过下面两种方式使用,但是第一种写起来很麻烦,于是有了第二行的语法糖,一般使用右箭头写法。
(*s).id;
s->id;
16.3编码规范
起别名,起了别名以后,就可以不用标签了,直接使用别名,但是在实际操作中,学linux的时候,会大量使用标签,而不是起别名
typedef struct student {
int id;
char name[25];
char sex[10];
}Student;
结构体本质上就是大一点的类型
struct INT1{
int a;
}x,y,z
上面的操作就类似于
int x,y,z;
不要用重命名把指针隐藏!
下面这种写法是非常不建议的
//结构体的定义
typedef struct student {
int id;
char name[25];
char sex[10];
}Student,*pStudent;
上代码做的事情其实就是下面这两件,代码效果是一样的,C目前没有被废弃的理由就是指针,没有指针的C是没有灵魂的,这种做法把指针隐藏了,但本质上还是指针,还降低的代码的可读性,难以区分是否是指针
//结构体的定义
typedef struct student {
int id;
char name[25];
char sex[10];
}Student;
typedef Student* pStudent;
17.枚举
枚举的作用是表示一些离散值
enum Suit{
DIAMOND,
CLUB = 4,
HEAET = 10,
SPADE
};
int main(){
enum Suit suit = DIAMOND;
return 0;
}
这个类型取值只能去枚举里面的值
18.动态内存分配
18.1堆与栈空间
堆的空间管理很麻烦,但是限制比较少,可以存储动态大小,堆的空间往往很大以GB为单位。
栈的空间管理很方便,但是有限制的,不能存储动态大小的数据,栈的空间很小,往往以MB为单位,栈上最好不要放线程共享数据。
18.2堆的申请
void* malloc(size_t size):
分配 size 个字节的内存块,不对内存块进行清零;如果无法分配指定大小的内存块,返回空指针。需要和free搭配使用。分配
void* calloc(size_tnmemb,size_t size):
为有 nmemb 个元素的数组分配内存块,其中每个元素占 size 个字节,并且对内存块进行清零;如果无法分配指定大小的内存块,返回空指针。
void* realloc(void *ptr,size_t size):
调整先前分配内存块的大小。如果重新分配内存大小成功,返回指向新内存块的指针,否则返回空指针。