C语言学习补充

00.环境配置

0.1 VsCode配置C/C++环境

参考:

https://www.bilibili.com/video/BV19c411G7ey/?p=1&spm_id_from=pageDriver&vd_source=d1fd4bcc46805ab35cc8bbb5a8bf318f

(1)安装VsCode;

(2)VsCode汉化;

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

(3)安装gcc编译器MinGW;

①安装;

②配置环境变量gcc编译器环境变量:

在这里插入图片描述

③验证环境变量是否配置好;

在这里插入图片描述
(4)配置C环境

①安装C/C++扩展

在这里插入图片描述
②配置任务,选择编译器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置"tasks.json"文件

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "cppbuild",
			"label": "C/C++: gcc.exe 生成活动文件",
			"command": "F:\\Qt\\Qt6.4.2\\Qt6.4.2\\Tools\\mingw1120_64\\bin\\gcc.exe",
			"args": [
				"-fdiagnostics-color=always",
				"-g",
				// "${file}",                    //默认,注释
				"*.c",                           //增加,使得当前文件夹下可编译多个".c"文件
				"-o",
				// "${fileDirname}\\${fileBasenameNoExtension}.exe"            //生成的可执行文件名称命名方式
				"${fileDirname}\\a.exe"                                        //修改后生成的可执行文件命名为"a.exe"
			],
			"options": {
				"cwd": "${fileDirname}"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": {
				"kind": "build",
				"isDefault": true
			},
			"detail": "编译器: F:\\Qt\\Qt6.4.2\\Qt6.4.2\\Tools\\mingw1120_64\\bin\\gcc.exe"
		}
	]
}

(5)修改调试配置文件

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

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) 启动",
            "type": "cppdbg",
            "request": "launch",
            // "program": "输入程序名称,例如 ${workspaceFolder}/a.exe",
            "program": "${fileDirname}\\a.exe",            //需要调试的可执行程序,与tasks.json文件保持一致                     
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            // "miDebuggerPath": "/path/to/gdb",        
            "miDebuggerPath": "F:\\Qt\\Qt6.4.2\\Qt6.4.2\\Tools\\mingw1120_64\\bin\\gdb.exe",            //gdb位置,与gcc位于同一路径下
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "将反汇编风格设置为 Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ]
        }


    ]
}

01.第1阶段:C语言基础

第01章 C语言概述

1.1 什么是C语言

通俗地讲,语言是人和人交流,C语言是人和机器交流。

1.2 C语言优缺点

1.2.1 C语言优点

(1)代码量小;

(2)执行速度快;

(3)功能其强大;

(4)编程自由;

1.2.2 C语言缺点

(1)写代码实现周期长;

(2)可移植性较差;

(3)过于自由,经验不足易出错;

(4)对平台库依赖较多;

1.3 C语言应用领域

在这里插入图片描述

1.4 C语言的简洁

C语言仅有32个关键字,9种控制语句,34种运算符,却能完成无数的功能:

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

1.5 第1个C语言程序:HelloWorld!

/*
*文件名称:HelloWorld.c
*编码:utf-8
*功能:输出“HelloWorld!”
*作者:xuhc
*编写日期:2024.06.28
*/
#include<stdio.h>
int main()
{
    //这是第一个C语言代码
    printf("HelloWorld!\n");
    return 0;
}
1.5.1 通过gcc编译c代码

编译命令格式:

gcc [-option1]...<filename>
g++ [-option1]...<filename>

命令、选项和源文件之间使用空格分隔;

一行命令中可以有零个、一个或多个选项;

文件名可以包含文件的绝对路径,也可以使用相对路径;

如果命令中不包含输出可执行文件的文件名,可执行文件的文件名会自动生成一个默认名,Linux平台为a.out,Windows平台为a.exe。

gcc、g++编译常用选项说明:

选项含义
-o file指定生成的输出文件名为file
-E只进行预处理
-S(大写)只进行预处理和编译
-c(小写)只进行预处理、编译和汇编
在这里插入图片描述
1.5.2 代码分析

(1)include头文件

#include的意思是头文件包含,#include <stdio.h>代表包含stdio.h这个头文件;

使用C语言库函数需要提前包含库函数对应的头文件,如这里使用了printf()函数,需要包含stdio.h头文件;

可以通过man 3 printf查看printf所需的头文件;

#include< > 与 #include "“的区别:

< > :表示系统直接按系统指定的目录检索

“” :表示系统先在 “” 指定的路径(没写路径代表当前路径)查找头文件,如果找不到,再按系统指定的目录检索

(2)main函数
一个完整的C语言程序,是由一个、且只能有一个main()函数(又称主函数,必须有)和若干个其他函数结合而成(可选)。

main函数是C语言程序的入口,程序是从main函数开始执行。

(3){} 括号,程序体和代码块

{}叫代码块,一个代码块内部可以有一条或者多条语句

C语言每句可执行代码都是”;"分号结尾

所有的#开头的行,都代表预编译指令,预编译指令行结尾是没有分号的

所有的可执行语句必须是在代码块里面

(4)注释
//叫行注释,注释的内容编译器是忽略的,注释主要的作用是在代码中加一些说明和解释,这样有利于代码的阅读

/**/叫块注释

块注释是C语言标准的注释方法

行注释是从C++语言借鉴过来的

(5)printf函数

printf是C语言库函数,功能是向标准输出设备输出一个字符串。

printf(“hello world\n”);//\n的意思是回车换行

(6)return语句
return代表函数执行完毕,返回return代表函数的终止;

如果main定义的时候前面是int,那么return后面就需要写一个整数;如果main定义的时候前面是void,那么return后面什么也不需要写;

在main函数中return 0代表程序执行成功,return -1代表程序执行失败;

int main()和void main()在C语言中是一样的,但C++只接受int main这种定义方式。

1.6 system函数

1.6.1 system函数的使用
#include<stdlib.h>
int system(const char *command)
/*
功能:在已经运行的程序中执行另外一个外部程序
参数:外部可执行程序名字
返回值:
    成功:0
    失败:任意数字
*/

示例

/*
*文件名称:system_function.c
*编码:utf-8
*功能:测试system函数,启动计算器
*作者:xuhc
*编写日期:2024.03.25
*/

#include<stdio.h>
#include<stdlib.h>
// int system(const char *command)
/*
功能:在已经运行的程序中执行另外一个外部程序
参数:外部可执行程序名字
返回值:
    成功:0
    失败:任意数字
*/
int main()
{
    system("calc");   //Windows平台
    // system("ls");     //Linux平台,需要头文件<stdlib.h>
    return 0;
}

1.7 C语言编译过程

1.7.1 C程序编译步骤

C代码编译成可执行程序经过4步:

1)预处理:宏定义展开、头文件展开、条件编译等,同时将代码中的注释删除,这里并不会检查语法

2)编译:检查语法,将预处理后文件编译生成汇编文件

3)汇编:将汇编文件生成目标文件(二进制文件)

4)链接:C语言写的程序是需要依赖各种库的,所以编译之后还需要把库链接到最终的可执行程序中去

在这里插入图片描述

1.7.2 gcc编译过程

(1)分步编译

预处理:
gcc -E hello.c -o hello.i
编译:
gcc -S hello.i -o hello.s
汇编:
gcc -c hello.s -o hello.o
链接:
gcc hello.o -o hello
选项含义
-o file指定生成的输出文件名为file
-E只进行预处理
-S(大写)只进行预处理和编译
-c(小写)只进行预处理、编译和汇编
################################################
文件后缀含义
.cC语言文件
.i预处理后的C语言文件
.s编译后的汇编文件
.o编译后的目标文件
在这里插入图片描述

(2)一步编译

gcc hello.c -o demo(还是经过:预处理、编译、汇编、链接的过程)

在这里插入图片描述

1.7.3 查找程序所依赖的动态库

Windows平台下,需要相应软件(Depends.exe):

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

1.8 CPU内构与寄存器部结

1.8.1 64位和32位系统区别

寄存器是CPU内部最基本的存储单元

CPU对外是通过总线(地址、控制、数据)来和外部设备交互的,总线的宽度是8位,同时CPU的寄存器也是8位,那么这个CPU就叫8位CPU

如果总线是32位,寄存器也是32位的,那么这个CPU就是32位CPU

有一种CPU内部的寄存器是32位的,但总线是16位,准32为CPU

所有的64位CPU兼容32位的指令,32位要兼容16位的指令,所以在64位的CPU上是可以识别32位的指令

在64位的CPU构架上运行了64位的软件操作系统,那么这个系统是64位

在64位的CPU构架上,运行了32位的软件操作系统,那么这个系统就是32位

64位的软件不能运行在32位的CPU之上

1.8.2 寄存器名字
8位16位32位64位
AAXEAXRAX
BBXEBXRBX
CCXECXRCX
DDXEDXRDX
1.8.3 寄存器、缓存、内存三者关系

按与CPU远近来分,离得最近的是寄存器,然后缓存(CPU缓存),最后内存。

CPU计算时,先预先把要用的数据从硬盘读到内存,然后再把即将要用的数据读到寄存器。于是 CPU<—>寄存器<—>内存,这就是它们之间的信息交换。

那为什么有缓存呢?因为如果经常操作内存中的同一址地的数据,就会影响速度。于是就在寄存器与内存之间设置一个缓存。

因为从缓存提取的速度远高于内存。当然缓存的价格肯定远远高于内存,不然的话,机器里就没有内存的存在。

由此可以看出,从远近来看:CPU〈—〉寄存器〈—> 缓存 <—> 内存。

1.9汇编语言

1.9.1 VS中C语言嵌套汇编代码
#include <stdio.h>

int main()
{
	//定义整型变量a, b, c
	int a;
	int b;
	int c;

	__asm
	{
		mov a, 3	//3的值放在a对应内存的位置
		mov b, 4	//4的值放在b对应内存的位置
		mov eax, a	//把a内存的值放在eax寄存器
		add eax, b	//eax和b相加,结果放在eax
		mov c, eax	//eax的值放在c中
	}
	
	printf("%d\n",  c);//把c的值输出

	return 0;//成功完成
}
1.9.2 反汇编
#include <stdio.h>

int main()
{
	//定义整型变量a, b, c
	int a;
	int b;
	int c;

	a = 3;
	b = 4;
	c = a + b;
	
	printf("%d\n",  c);//把c的值输出

	return 0;//成功完成
}

(1)设置断点F9

在这里插入图片描述
(2)选择反汇编按钮

在这里插入图片描述
(3)根据汇编代码分析程序

在这里插入图片描述

1.10 集成开发环境IDE

集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。所有具备这一特性的软件或者软件套(组)都可以叫集成开发环境。

1.10.1 Qt Creator

常用快捷键

快捷键含义
Ctrl + i自动格式化代码
Ctrl + /注释/取消注释
Alt + Enter自动完成类函数定义
F4.h文件和对应.cpp 文件切换
F9设置断点
F5调试运行
Ctrl + r编译,但不调试运行
Ctrl + b编译,不运行
F10next调试
F11step调试
1.10.2 Microsoft Visual Studio

(1)常用快捷键

快捷键含义
Ctrl + k,Ctrl + f自动格式化代码
Ctrl + k,Ctrl + c注释代码
Ctrl + k,Ctrl + u取消注释代码
F9设置断点
F5调试运行
Ctrl + F5不调试运行
Ctrl + Shift + b编译,不运行
F10next调试
F11step调试
(2)Visual Studio的C4996错误
由于微软在Visual Studio中不建议再使用C的传统库函数scanf,strcpy,sprintf等,所以直接使用这些库函数会提示C4996错误:

在这里插入图片描述

VS建议采用带_s的函数,如scanf_s、strcpy_s,但这些并不是标准C函数。

要想继续使用此函数,需要在源文件中添加以下指令就可以避免这个错误提示:

#define _CRT_SECURE_NO_WARNINGS     //这个宏定义最好要放到.c文件的第一行
#pragma warning(disable:4996)	   //或者使用这个

第02章 数据类型

2.1 常量与变量

2.1.1 关键字

在这里插入图片描述

2.1.2 数据类型

数据类型的作用:编译器预算对象(变量)分配的内存空间大小。

在这里插入图片描述

2.1.3 常量

常量:

在程序运行过程中,其值不能被改变的量

常量一般出现在表达式或赋值语句中

整型常量100,200,-100,0
实型常量3.14 , 0.125,-3.123
字符型常量‘a’,‘b’,‘1’,‘\n’
字符串常量“a”,“ab”,“12356”

2.1.4 变量

(1)变量

变量:

在程序运行过程中,其值可以改变;

变量在使用前必须先定义,定义变量前必须有相应的数据类型;

标识符命名规则:

标识符不能是关键字;

标识符只能由字母、数字、下划线组成;

第一个字符必须为字母或下划线;

标识符中字母区分大小写;

变量特点:

变量在编译时为其分配相应的内存空间;

可以通过其名字和地址访问相应内存;

在这里插入图片描述
(2)声明和定义区别

声明变量不需要建立存储空间,如:extern int a;

定义变量需要建立存储空间,如:int b;

#include<stdio.h>
int main()
{
    //extern关键字只做声明,不能做任何定义
    //声明一个变量a,a在这里没有建立存储空间
    extern int a;
    a = 10;          // err,没有空间,就不可以赋值
    int b = 10;      // 定义一个变量b,b的类型为int,b赋值为10
    return 0;
}

从广义的角度来讲声明中包含着定义,即定义是声明的一个特例,所以并非所有的声明都是定义:

int b 它既是声明,同时又是定义

对于 extern b来讲它只是声明不是定义

一般的情况下,把建立存储空间的声明称之为“定义”,而把不需要建立存储空间的声明称之为“声明”。

2.1.5 使用示例

#include<stdio.h>
#define MAX 10 //声明了一个常量,名字叫MAX,值是10,常量的值一旦初始化不可改
int main()
{
    int a;        //定义了一个变量,其类型为int,名字叫a
    const int b = 10;     // 定义一个const常量,名为叫b,值为10
    //b=11;       //err,常量的值不能改变
    //MAX = 100;  //err,常量的值不能改变
    a = MAX;      //将a的值设置为MAX的值
    a = 123;
    printf("%d\n",a);    //打印变量a的值
    return 0;
}

2.2 整型:int

2.2.1 整型变量的定义和输出
打印格式含义
%d输出一个有符号的10进制int类型
%o(字母o)输出8进制的int类型
%x输出16进制的int类型,字母以小写输出
%X输出16进制的int类型,字母以大写输出
%u输出一个10进制的无符号数
#include<stdio.h>

int main()
{
    int a = 123;           //定义变量a,以10进制方式赋值123
    int b = 0567;          //定义变量b,以8进制方式赋值0567
    int c = 0xabc;         //定义变量c,以16进制方式赋值为0xabc
    printf("a=%d\n",a);
    printf("8进制:b=%o\n",b);
    printf("10进制:b=%d\n",b);
    printf("16进制:c=%x\n",c);
    printf("16进制:c=%X\n",c);
    printf("10进制:c=%d\n",c);

    unsigned int d = 0xffffffff;        //定义无符号int变量d,以16进制方式赋值
    printf("有符号方式打印:d=%d\n",d);
    printf("无符号方式打印:d=%u\n",d);
    return 0;
}
2.2.2 整型变量的输入
#include<stdio.h>
int main()
{
    int a;
    printf("请输入a的值:");
    //不要加"\n"
    scanf_s("%d",&a);
    printf("a=%d\n",a);       //打印a的值
    return 0;
}
2.2.3 short、int、long、long long
数据类型占用空间
short(短整型)2字节
int(整型)4字节
long(长整形)Windows为4字节,Linux为4字节(32位),8字节(64位)
long long(长长整形)8字节

注意:

需要注意的是,整型数据在内存中占的字节数与所选择的操作系统有关。虽然C语言标准中没有明确规定整型数据的长度,但 long 类型整数的长度不能短于 int 类型, short 类型整数的长度不能长于int类型。

当一个小的数据类型赋值给一个大的数据类型,不会出错,因为编译器会自动转化。但当一个大的类型赋值给一个小的数据类型,那么就可能丢失高位。

整型常量所需类型
10代表int类型
10l, 10L代表long类型
10ll, 10LL代表long long类型
10u, 10U代表unsigned int类型
10ul, 10UL代表unsigned long类型
10ull, 10ULL代表unsigned long long类型
打印格式含义
%hd输出short类型
%d输出int类型
%ld输出long类型
%lld输出long long类型
%hu输出unsigned short类型
%u输出unsigned int类型
%lu输出unsigned long类型
%llu输出unsigned long long类型
#include<stdio.h>
int main()
{
    short a = 10;
    int b = 10;
    long c = 10l;     //或者10L
    long long d = 10ll;   //或者10LL
    printf("sizeof(a)=%u\n",sizeof(a));
    printf("sizeof(b)=%u\n",sizeof(b));
    printf("sizeof(c)=%u\n",sizeof(c));
    printf("sizeof(d)=%u\n",sizeof(d));
    printf("short a = %hd\n",a);
    printf("int b = %d\n",b);
    printf("long c = %ld\n",c);
    printf("long long d = % lld\n",d);
    unsigned short a2 = 20u;
    unsigned int b2 = 20u;
    unsigned long c2 = 20ul;
    unsigned long long d2 = 20ull;
    printf("unsigned short a = %hu\n",a2);
    printf("unsigned int b = %u\n",b2);
    printf("unsigned long c = %lu\n",c2);
    printf("unsigned long long d = %llu\n",d2);
    return 0;
}
2.2.4 有符号数和无符号数区别

(1)有符号数

有符号数最高位为符号位,0代表正数,1代表负数。

#include<stdio.h>
int main()
{
    signed int a = -1089474374;            //定义有符号整型变量a
    printf("%X\n",a);                      //结果为BF0FF0BA
    //B    F    0    F    F    0    B    A
    //1011 1111 0000 1111 1111 0000 1011 1010
    return 0;
}

(2)无符号数

无符号数最高位不是符号位,而就是数的一部分,无符号数不可能是负数。

1011 1111 0000 1111 1111 0000 1011 1010:

如果当无符号数看待,那么它是一个整数的源码

原码:1100 0000 1111 0000 0000 1111 0100 0110

C 0 F 0 0 F 4 6

十进制数:3236958022

#include<stdio.h>
int main()
{
    unsigned int a = 3236958022;      //定义无符号整型变量a
    printf("%X\n",a);                 //结果为C0F00F46
    return 0;
}

(3)有符号和无符号整型取值范围

数据类型占用空间取值范围
short2字节-32768 到 32767 (-2
int4字节-2147483648 到 2147483647 (-231 ~ 231-1)
long4字节-2147483648 到 2147483647 (-231 ~ 231-1)
unsigned short2字节0 到 65535 (0 ~ 216-1)
unsigned int4字节0 到 4294967295 (0 ~ 232-1)
unsigned long4字节0 到 4294967295 (0 ~ 232-1)

2.3 sizeof关键字

sizeof不是函数,所以不需要包含任何头文件,它的功能是计算一个数据类型的大小,单位为字节

sizeof的返回值为size_t

size_t类型在32位操作系统下是unsigned int,是一个无符号的整数

推荐课程:
https://xxetb.xetslk.com/s/vgpHh

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值