c语言学习笔记
一.C语言准备
- 1.肯汤姆森和丹尼斯里奇为写unix系统创建在1973年创建了c语言
- 2.c语言运行机制流程
main.c(源文件)->预处理(取出多余的的空格和注释)->main.i(预处理的文件)->编译->main.s汇编程序->汇编->main.obj(二进制)->和库文件链接->main.exe(可执行文件)
- 3.gcc是GNU compiler collection的缩写,是gnu开发的编程语言编译器,编译套件包括了c,c++,Fortran,Java,Ada,go,也包含了一些语言库。
二.c语言基础
1.整型的类型
- 有符号的int和无符号的int相加就是先将有符号的int转换成无符号的int然后相加。
- math头文件中的函数
2.printf中的占位符
printf | f-》float | f-》double | lf-》long double |
scanf | f-》float | lf-》double | Lf-》long double |
占位符 | 含义 |
---|---|
%zu | 为sizeof的专门占位符 |
%p | 是打印地址(指针地址)的,是十六进制的形式, |
%.2f | 保留两位小数 |
%e | 科学计数法 |
3.头文件错误
1.问题描述
系统重装后,把vscode、里面的c\c++插件和编译环境minGW装上后,并将minGW的环境变量配置好后,发现否文件出现了问题,运行后报如下错误:
而且在程序的终端运行 查看minGW的版本号也无效。
2.解决办法
1.按住 win+R 在框框中输入 cmd,进入到 dos 界面,再输入 gcc -v -E -x c++ -
,如下图示。
2.然后将鼠标放在头文件中点击快速修复。
note 这里可能出现没有这个选项的情况
这时候在settings中找到扩展中的intellSense中的include Path把上面dos中查找到的路径添加到其中就会出现。
3.选择编辑“include Path”设置
这个时候可能在复制的前面有空格的话就需手动删除,否则就会出现打开项目的文件路径拼接。
4.保存重启软件后问题就解决啦。
note: 在修改了一些配置的时候如果不重启,有的就不生效,可能就会出现你早把问题解决了,还一直报错。所以实在不行,没有招后先重启一下看情况看看问题解决没。
3.头文件知识
1.头文件的引用自己写的就是“”,标准的一般使用<>.
2.当我们使用<>包含的一个头文件时,文件的搜索顺序为
-
通过GCC参数 gcc-I 指定的目录(注:大写的 i)
-
通过环境变量 CINCLUDEPATH 指定的目录
-
GCC 的内定目录
-
搜索规则:当不同目录下存在相同的头文件时,先搜到那个使用哪个,搜索停止
3.使用“”时先扫描当前文件的文件路径然后在扫描上面的。
**tip:**如果是自己下载的头文件或者是自己写的头文件,想要把他放在自己定义的路径文件夹中。方便以后自己的增加和删除。就需要配置.vscode文件夹中的tasks.json文件在args列表中添加-I加文件路径。
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc.exe build active file",
"command": "D:\\soft\\codeSoft\\minGW64\\mingw64\\bin\\gcc.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"-I",
"D:\\soft\\codeSoft\\minGW64\\includeZls\\uthash"
],
-
一些task中的参数用方法
1.-I
(大写的i)-I
参数是用来指定头文件所在目录。
/usr/include
目录一般是不用指定的,gcc知道去那里找,但是如果头文件不在/usr/include
里我们就要用-I
参数指定了。
2.-L
(大写的l)-L
参数跟着的是库文件所在的目录。
3.-l
(小写的L)-l
参数就是用来指定程序要链接的库,-l参数紧接着就是库名。
4.ldd
ldd
用来打印或者查看程序运行所需的共享库。
4.换行和回车的区别
C语言中,换行,回车分别是'\n'
和'\r'
;
换行,是换到下一行。
回车,只是回到本行开头。
在windows/dos系统中,我们通常说的回车,也就是键盘的enter键实际包含了回车换行。在这样的系统中,'\n’的作用不仅仅是换到下一行,而且换到了下一行的开头了。
5.malloc动态分配空间函数何时使用
- 在定义一个没有指向具体变量的指针式使用
- 在定义一个链表的时候后使用,用来指定这个链表的长度。
- 具体详情
-
6.void
void* 可以指向任意的数据类型。但是其他类型的指针不能指向viod指针。
7.x64和x86的区别
8.关键字
- typedef、extern、static、auto、register属于存储类型说明符,一条语句中只能出现一个
7.运算符
- c语言中没有乘方运算符。
8.数组
- 数组在初始化的时候如果没有初始化完后面没有初始化的就自动补零。
- 如果没有初始化,数组中的值是随机的。
- 初始化的时候超出所定义的下表,则直接去前面的后面的忽略。
- 在使用的使用数组元素的时候,如果超出定义的下表,则刚开始里面的值是随机的。
9.活动代码页
- 可以用
chcp
临时改变终端输出的字符编码集。
10.函数的声明
- 没有在main()主函数前面声名自己定义的函数,编译器会自己隐式的声名函数,但是默认返回值是int,如果自己定义的函数返回值类型是其他类型,则就会报错。
- 在main()函数前声名自己的定义的函数,只需要声名返回值,函数名称,函数的参数。
char myFunction(int,char);
int main(){
//函数的主要逻辑
return 0;
}
char myFunction( int arg1,char arg2){
//函数的主要逻辑
return returnArg;
}
11.static关键字
- 静态局部变量:变量存放在静态区,每次函数调用结束之后,变量分配的空间不回收,下一次调用的时候接着上一次的值使用。
- 静态全局变量:其他文件中的函数不可以使用静态全局变量,也就相当于本文件的全局变量,并不是本项目的全局变量。
12.sprintf和sscanf
- 代码展示:
//字符串输入输出
//输出到字符串
char outputString[30];
int age=18;
char name[6]="李华";
double score=99.9;
sprintf(outputString,"name=%s,age=%d,score=%lf\n",name,age,score);
printf("%s",(outputString));
printf("===============\n");
char input[100]="我叫菜鸡,我今年18,我的成绩为99.99";
sscanf(input,"我叫%6s,我今年%d,我的成绩为%lf",name,&age,&score);
printf("%s\n",name);
printf("%d\n",age);
printf("%lf\n",score);
printf("name=%s,age=%d,score=%lf",name,age,score);
2.结果展示
3.注意
- 其中中文字符在c中占用3个字节
- sscanf用到的 %s占位符 在使用的时候需要 指定转换的字符传的长度 。否则默认匹配到以斜杠零结尾。
- sprintf是把输出的格式顺便记录在一个字符传中。
- sscanf是将字符串中的某些部分提取到各个变量中。
- 还有就是匹配的字符串变量要和自己引号中的字符串除配部分完全一样。
13.指针
1. 指针的声明
- 数据类型 *指针变量 [=初始地址值];
//都合法
int *ptr;//直接统一用这种
int* ptr;
int * ptr;
2.同类型的指针相减
得到的数据类型为 | ptrdiff_t |
---|---|
意思 | 为相隔几个元素 |
输出占位符为 | %dt |
3.数组名和指针
- 数组名单独拿出来就是一个地址。
- 数组名和指针的区别:指针可以修改,数组名不可以修改。
- 数组名不能自增自减。
- 数组名代表这整个数组。
sizeof(num)
这个是整个数组的大小,sizeof(ptr)
则是系统地址所占的大小。
4.数组指针
指向数组的指针。
//数组指针
int arr[]={1,2,3,4,5};
//这个时候就是类型转换了,把int* 转化为了int(*)[5]类型
//int (*arrPtr)[5]=arr;
//这个时候需要取出数组类的地址,然后在赋值
int (*arrPtr)[5]=&arr;
printf("arrPtr=%p\n",arrPtr);
printf("arr的值:%p\n",arr);
printf("&arr=%p\n",&arr);
//这三个输出的值都是一样的
14.结构体
- 赋值
15.输入函数和’\n’
scanf
sscanf
sgets
gets
getchar
解答