一、部署开发环境及工具
1、安装 C语言编译器 MinGW-w64:
MinGW 的全称是:Minimalist GNU on Windows ,它实际上是将经典的开源 C语言 编译器 GCC 移植到了 Windows 平台下
官方下载地址:https://sourceforge.net/projects/mingw-w64/files/
我下载的版本:x86_64-posix-seh
2、CMake是一个跨平台的编译(Build)工具:
cmake官方下载地址:https://cmake.org/download/
我下载的版本:cmake-3.24.0-rc2-windows-x86_64.zip
(1)有效地描述这些文件之间的依赖关系以及处理命令,当个别文件改动后仅执行必要的处理,而不必重复整个编译过程,可以大大提高软件开发的效率;
(2)框架的使用者们只需要在下载源码的同时下载作者提供的CMakeLists.txt,就可以利用CMake,在”原作者的帮助下“进行工程的搭建;
(3)makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作;
(4)makefile带来的好处就是——"自动化编译",一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率;
3、添加环境变量
下载之后解压,复制到D盘,路径如下:
D
|__c
|___cmake-3.24.0-rc2-windows-x86_64
|___mingw64
系统变量 -> path -> 增加下面两条 D:\c\mingw64\bin D:\c\cmake-3.24.0-rc2-windows-x86_64\bin
4、vscode配置,简单项目使用vscode开发
5、Clion配置,复杂项目使用Clion开发
二、第一个c程序
? 基于g++编译单文件,生成带调试信息的可执行文件、并调试
g++ -g main.cpp -o my-single-swap
? 基于g++编译多文件,生成带调试信息的可执行文件、并调试
g++ -g main.cpp -o my-multi-swap
-
基于cmake 编写最简单的CMakeLists.txt
三、程序框架
#include <stdio.h>
int main()
{
return 0;
}
1、输出
# \n 换行符
printf("Hello World! \n");
2、变量
变量定义
类型名称 变量名称
int price
变量初始化
类型名称 变量名称 = 初始值
int price = 0;
3、常量:固定不变的数
const int AMOUNT = 100;
4、数据类型
CPU的工作原理:CPU的控制器从内存读取一条指令并放入寄存器
-
数据范围:char < short < int < float < double 我们在说一个计算机的字长的时候,我们指的是这台计算机的cpu里面的寄存器一次处理数据的长度(32位 / 64位),也是cpu通过总线每次从内存中取数据的长度(32位 / 64位),也是总线一次可以传输的数据长度(32位 / 64位); # 字节和字符的区别
字节是一个单位,表示在内存当中的大小,1字节是8个二进制的位,1个字节等于8位(bit,比特);
字节是指一小组相邻的二进制数码。通常是8位作为一个字节。它是构成信息的一个小单位,并作为一个整体来参加操作;
1GB=1024MB
1MB=1024KB
1KB=1024bit
字符是C语言的一种数据类型,通常是char,不同语言,占据不同字节大小;
(1) ASCII码:
1个英文字母 占 1个字节;
1个中文汉字 占 2个字节;
(2) UTF-8编码:
1个英文字母 占 1个字节;
1个中文汉字 占 3个字节;
(3) Unicode编码:
1个英文字母 占 2个字节;
1个中文汉字 占 2个字节;
-
所占内存的大小:1字节到16字节,在计算机内部一切都是二进制 char 占 1字节 整数范围 -128 ~ 127
short 占 2字节 整数范围 -32768 ~ 32767
int 占 4字节 大小取决于编译器(cpu) 在C语言中 int 表达的是一个寄存器的大小(选择整数数据类型时,选用int,其他类型在计算机中存储可能也是int)
long 占 8字节 大小取决于编译器(cpu)
float 占 4字节
double 占 8字节 (选择浮点数据类型时,选用double,在计算机内存中cpu一次处理的能力刚好是一个double)
-
内存中的表达式:二进制数(补码)、编码
sizeof():给出某个类型或变量在内存中所占据的字节数;
-
整数 int
输入 --> scanf("%d", ...)
输出 --> printf("%d", ...)
char
输入 --> scanf("%c", ...)
输出 --> printf("%c", ...)
short
long
-
浮点数 float 单精度
double 双精度
输入 --> scanf("%lf", ...)
输出 --> printf("%f", ...)
-
逻辑 bool
-
指针:保存地址的变量 int var = 20;
& --> 取变量的地址; ----> 输出 printf("%p", &a)
int *ip;
ip = &var;
printf("var 变量的地址: %p\n", &var );
printf("ip 变量存储的地址: %p\n", ip );
printf("*ip 变量的值: %d\n", *ip );
-
自定义类型
说明:
int a = 10;
(1) 变量a 本质上代表一个存储单元;
(2) CPU通过该存储单元的地址,访问该存储单元中的数据;
(3) 所以a本来代表两个值:存储单元的地址和储单元中的数据;
(4) 于是就有了二异性。为了消除这种二义性,C语言规定a表示存储单元中的数据,&a表示存储单元的地址;
(5) a存储单元中的数据可以是一个普通数值,也可以是另一个存储单元的地址,比如:a = &b; 语句就是将b的存储单元的地址存入a存储单元中;
(6) C语言规定 *a代表 a中存储的地址对应的存储单元中的数据,也就是访问*a就等于访问b,于是*a提供了通过a访问b中的数据的手段。
(7) 在C语言里地址叫指针
(8) 在C语言中的数组本质上其实也是指针,即:*a 等同于 a[]
a表示a对应的存储单元中的数据。
&a表示a对应的存储单元的地址。
*a表示:首先,要求a对应的存储单元中的数据一定是另一个存储单元的地址。
于是,*a表示另一个存储单元中的数据。
当a声明的类型是int时,a中存储的是一个整数数值,通过a可以访问(读取或修改)这个数值。
当a声明的类型是int*时,a中存储的是一个存储单元的地址,而该存储单元中存储的数据是一个整数数值;通过*a可以访问(读取或修改)这个数值。a == &*a 都是该存储单元的地址。
当a声明的类型是int**时,a中存储的是一个存储单元的地址,而该存储单元中存储的数据是另外一个存储单元的地址,另外这个存储单元中存储的是一个整数数值;通过**a可以访问(读取或修改)这个数值。
5、运算符
表达式 | 运算 | 表达式的值 |
---|
count++ | 给count加1 | count原来的值 | ++count | 给count加1 | count+1以后的值 | count– | 给count减1 | count原来的值 | –count | 给count减1 | count-1以后的值 |
完全可以只用count++ 和 count–,和golang 保持一致
6、代码风格
if ( a==0 ) {
x = 1;
} else if ( a==1 ) {
x = 2;
} else {
x = 3;
}
int type;
switch (type) {
case 1:
printf("早上好!");
break;
case 2:
printf("中午好!");
break;
case 3:
printf("晚上好!");
break;
default:
printf("再见!");
break;
}
7、循环语句
int n = 6;
int i = 1;
int fact = 0;
for (i=1; i<=n; i++) {
fact += i;
}
printf("n = %d, fact = %d\n", n, fact);
8、函数定义:函数是一块代码,接收零个或多个参数,做一件事情,并返回零个或一个值
void sum( int begin, int end ){
int i;
int sum = 0;
for ( i=begin; i<=end, i++ ){
sum+=i;
}
}
void 返回结果占位符(使用void表示不返回结果),可以指定返回结果的类型如:int,double,bool
C语言中值传递、指针传递和引用传递
传递方式 | 函数定义 | 函数调用 | 函数内对a修改的影响 |
---|
值传递 | fun(int a) | fun(x) | 外部x不变 | 指针传递 | fun(int *a) | fun(&x) | 外部x同步更改 | 引用传递 | fun(int &a) | fun(x) | 外部x同步更改 |
9、数组
(1)定义数组
type arrayName [ arraySize ];
eg:
长度固定:double weight [ 3 ];
长度不定:double height [];
type C数据类型
arrayName 数组名称
arraySize 数组长度
二维数组
int a[2][4];
int a[2][4] = {
{1, 2, 3, 4},
{6, 7, 8, 9},
};
a[0][1]=20;
(2)数组初始化
double weight [3] = {46.2, 47.1, 49.6};
# 把数组weight 第2个元素的值,赋为 50.2
weight[2] = 50.2;
(3)访问数组元素,通过下标访问
double yi = weight[2];
10、enum(枚举)
(1)定义枚举
enum 枚举名 {枚举元素1,枚举元素2,……};
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
enum DAY day;
day = WED;
printf("%d",day);
11、C 字符串:
在 C 语言中,字符串实际上是使用空字符 \0 结尾的一维字符数组。因此,\0 是用于标记字符串的结束。
空字符(Null character)又称结束符,缩写 null,是一个数值为 0 的控制字符,\0 是转义字符,意思是告诉编译器,这不是字符 0,而是空字符。
(1)定义字符串
char [7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};
char site[] = "RUNOOB";
char *str = "RUNOOB";
(2)C 中有大量操作字符串的函数
序号 | 函数 & 目的 |
---|
1 | strcpy(s1, s2); 复制字符串 s2 到字符串 s1。 | 2 | strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。 | 3 | strlen(s1); 返回字符串 s1 的长度。 | 4 | strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。 | 5 | strchr(s1, ch); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 | 6 | strstr(s1, s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。 |
12、C 结构体
(1)定义结构体
struct Books
{
char title[50];
char author[50];
int book_id;
} book;
(2)结构体变量的初始化
#include <stdio.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book = {"C 语言", "RUNOOB", "编程语言", 123456};
int main()
{
printf("title : %s\nauthor: %s\nsubject: %s\nbook_id: %d\n", book.title, book.author, book.subject, book.book_id);
}
|