前言
如果觉的博主的文章还不错的话,还请点赞,收藏,关注支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。
本篇介绍C语言的一些基础知识
另分享一篇关于vs快捷键的博文可能对大家的工作有所帮助:
本篇暂时不深入讲解,后续会逐渐渗透
目录
1.什么是C语言
- C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易 的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
- 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的 C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超 级电脑等作业平台。
- c语言的研发时期大概在1972年,如下是2021年计算机语言的总榜,通过对比可知C语言是最值得信任的语言,c语言是鼻祖的存在,可想而知c语言对学习其他语言的帮助。
-
2.编程环境的构建
- C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。Gcc是最常用的编译器,但我们初学一般使用集成开发环境--IDE,如:Visual Studio 具体下载可参考我的另一篇博客:
3.C 程序结构
- 在我们学习 C 语言的基本构建块之前,让我们先来看看一个最小的 C 程序结构,在接下来的章节中可以以此作为参考。
C 程序主要包括以下部分:
- 预处理器指令
- 函数
- 变量
- 语句 & 表达式
-
C 语言有两种注释方式:
1
// 单行注释
以 // 开始的单行注释,这种注释可以单独占一行。
1
2
3
4
5
6
/* 单行注释 */
/*
多行注释
多行注释
多行注释
*/
/* */ 这种格式的注释可以单行或多行。
-
C Hello World 实例:
让我们看一段简单的代码,可以输出单词 "Hello World":
1 2 3 4 5 6 7 8 9 |
|
下面的这种代码也是可以的
int main(void)//void表示main函数不需要参数
{
return 0;
}
- 反例:
不建议这样写:
void main()
{
//这种写法是非常古老的
}不标准的写法:
main()
{
}
4. 数据类型
存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。
- 类型的使用:
- 整型:
char //字符数据类型short //短整型
int //整形long //长整型long long //更长的整形
- 浮点型:(即小数)
float //单精度浮点数,精确度低double //双精度浮点数,精确度高
#include <stdio.h>int main (){printf("%d\n", sizeof(char));
printf ( "%d\n" , sizeof ( short ));printf ( "%d\n" , sizeof ( int ));printf ( "%d\n" , sizeof ( long ));printf ( "%d\n" , sizeof ( long long )); // %d 打印10进制的整数printf ( "%d\n" , sizeof ( float ));printf ( "%d\n" , sizeof ( double ));printf ( "%d\n" , sizeof ( long double ));return 0 ;}
右侧所得单位为字节byte
电脑支持的是二进制语言
4.1 变量的命名
只能由字母(包括大写和小写)、数字和下划线( _ )组成。不能以数字开头。长度不能超过 63 个字符。变量名中区分大小写的。变量名不能使用关键字。
4.2 变量的分类
4.3变量的使用

#include <stdio.h>int main (){int num1 = 0 ;int num2 = 0 ;int sum = 0 ;printf ( " 输入两个操作数 :>" );scanf ( "%d %d" , & num1 , & num2 );sum = num1 + num2 ;printf ( "sum = %d\n" , sum );return 0 ;}
4.3 变量的作用域和生命周期
4.54常量(不变的量)
4.41 const 修饰的常变量
#include<stdio.h> int main() { int num = 10; num = 20; //改变了变量num的值 printf("%d\n", num); return 0; }
直接输入变量,可以看出通过第四行的操作直接改变了变量的输出值
当在变量前面输入const 如下:
#include<stdio.h> int main() { const int num = 10; num = 20; printf("%d\n", num); return 0; }
报错: 第四行左值指定说明变量的值不允许改了,说明coonst具有指定作用,这时候后面的值num就具有了常量的属性,但num本质还是一个变量,所以称之为常变量
综上const用于需要一个常量,但此值不能改的时候
4.42 #define 定义的标识符常量
代码如下:
如上图输出值为100,如果再输入MAX=200;会怎样呢?
如图,报错左操作数必须为左值,说明define定义的这个量是不可改变的即常量
4.43枚举常量
枚举>一一列举
c语言中的枚举类型num
如上输出值为0、1、2,是不可以改变的
需要注意的是enum下的标点符号
5. 字符串+转义字符+注释
5.1 字符串
“hello world”
#include<stdio.h>
int main() {
char arr1[] = "abc";
char arr2[] = { 'a','b','c' };
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
如图可监视到字符串的结束标志\0
arr2输出乱码,但如果在其后加入‘\0’就输出abc,这里就不演示了
另外想要输出字符串的长度可以使用strlen库函数(string length),需要注意的是包含头文件#include<string.h>
演示:
#include<stdio.h>
#include<string.h>
int main() {
char arr1[] = "abc";
char arr2[] = { 'a','b','c','\0' };
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
return 0;
}
结果:
下面这种方式arr2的输出值为随机值,因为没有\0
5.2 转义字符
#include <stdio.h>int main (){printf ( "c:\code\test.c\n" );return 0 ;}
\?
|
在书写连续多个问号时使用,防止他们被解析成三字母词
|
\'
|
用于表示字符常量
'
|
\“
|
用于表示一个字符串内部的双引号
|
\\
|
用于表示一个反斜杠,防止它被解释为一个转义序列符
|
\a
|
警告字符,蜂鸣
|
\b
|
退格符
|
\f
|
进纸符
|
\n
|
换行
|
\r
|
回车
|
\t
|
水平制表符 就是键盘上Tab的意思
|
\v
| 垂直制表符 |
\ddd
| ddd表示1-3个八进制的数字。
\130 X
|
\xdd
| dd表示2个十六进制的数字。
如:
\x30 0
|
现在一般不用
5.21 三字母词
如图??)或??(即为三转义字符分别代表】和【
如下图若用\加在?前则可防止编译器将他们翻译成三字母词,不过现在的编译器大多不支持三字母词,一些老旧编译器还是支持的
2.
如图想打印字符形式的单引号如图在单引号前加\即可实现,如图双引号类似
3.
如图,若想使 \t 不以转义字符的形式输出,则在其前加 \ ,正常输出。
5.22 \ddd
八进制数130转换成10进制数字,对应的值88 作为 ASCLL码值表示的字符是’X‘
5.23 xdd
八进制数字是0——7,所以输出14
6. 注释
7. 选择语句
if
#include <stdio.h>
int main()
{
int coding = 0;
printf("你会去敲代码吗?(选择1 or 0):>");
scanf("%d", &coding);
if(coding == 1)
{
prinf("坚持,你会有好offer\n");
}
else
{
printf("放弃,回家卖红薯\n");
}
return 0;
8. 循环语句
do ... while语句
这里暂时只接触一下while循环的实例
#include <stdio.h>
int main()
{
printf("规划学习\n");
int line = 0;
while(line<=20000)
{
line++;
printf("我要继续努力敲代码\n");
}
if(line>20000)
printf("好offer\n");
return 0; }
9. 函数
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}
上述代码,写成函数如下:
#include <stdio.h>
int Add(int x, int y)
{
int z = x+y;
return z;
}
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = Add(num1, num2);
printf("sum = %d\n", sum);
return 0;
}
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素
函数的特点就是简化代码,代码复用。
10. 数组
10.1 数组定义
int arr [ 10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };// 定义一个整形数组,最多放 10 个元素 //数组的初始化int arr[10] = {1,2,3};//不完全初始化,剩余的值为0int arr[ ] ={1,2,3};//不指定大小时,根据后面初始化的值输出int arr[ ] //这种写法是完全错误的,不指定大小必须进行初始化int arr[10]//随机值int main(){int n = 10;int arr[n];//c99 允许数组在创建的时候用变量指定数组大小,但是这种数组不能初始化return 0;}
10.2 数组的下标

10.3 数组的使用
#include <stdio.h>int main (){int i = 0 ;int arr [ 10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };for ( i = 0 ; i < 10 ; i ++ ){printf ( "%d " , arr [ i ]);}printf ( "\n" );return 0 ;}
11. 操作符
11.1 算术操作符
+ - * / % 前面三个和数学中基本一样,这里介绍一下后两个
#include<stdio.h>
int main() {
printf("%d\n", 7 / 2);//3
printf("%lf\n", 7 / 2.0);//3.50000
printf("%.1lf\n", 7.0 /2);//3.5
return 0;
}
int main() {
printf("%d\n", 7 % 2);//7/2=3……1
printf("%d\n", 8 % 2);//……0
}
11.2 移位操作符
>> << 向右向左移动二进制位这里涉及二进制的计算和存储,暂时不作介绍
11.3 位操作符
&按位与^按位异或|按位或
11.4 赋值操作符
= += -= *= /= &= ^ = |= >>= <<=
int main() {
int a = 10;//这就是赋值操作符
a = a + 5;
a += 5;
return 0;
}
如上a +=5;等价于a =a+5; 后面的 -= *= /= 与之类似
11.5 单目操作符
,只有一个数的操作符
! 逻辑反操作- 负值+ 正值& 取地址sizeof 操作数的类型长度(以字节为单位)~ 对一个数的二进制按位取反-- 前置、后置 --++ 前置、后置 ++* 间接访问操作符 ( 解引用操作符 )( 类型 ) 强制类型转换
这里首先介绍一下c语言中如何表示真假以便以下代码片段的理解:
0表示假
非0表示真
11.51 单目操作符(非)!
int main() { //
int a = 0; //
scanf("%d",&a); // 1
printf("%d\n", a); // 1
printf("%d\n", !a); // 0 //只有一个操作数a
}
c语言语法规定:当假变为真时输出固定值1,假一直为0,手动输入任何非0值都输出真
int main() {
int flag = 0;
if (flag)//flag为真,打印hehe
{
printf("hehe\n");
}
if (!flag)//flag为假打印haha
{
printf("haha\n");
}
return 0;
}
11.52 单目操作符 - +
int main()
{
int a = -10;
int b = -a; //通过-改变了a的符号
printf("%d\n", b);
}
int c = +a;
printf("%d\n", c);//这样输出无法改变a的正负
所以‘+’一般基本不用
11.53 单目操作符++ 和 --
后面所附数字是输出结果
11.6 关系操作符
>>=<<=!= 用于测试 “ 不相等 ”== 用于测试 “ 相等 ”
11.7 逻辑操作符
&& 逻辑与|| 逻辑或![]()
需要注意下面绿色的写法是错误的
11.8 条件操作符
exp1 ? exp2 : exp3 解析如下:exp1 ? exp2 : exp3表达式 判断真假 真执行 假执行
如图,若a>b为真,则输出a的值若a>b为假,则输出b的值
11.9 逗号表达式 下标引用、函数调用和结构成员
exp1 , exp2 , exp3 , …expN按顺序执行,结束出结果int main() { int a = 3; int b = 0; int c = 4; int d = (a=b-3,b=a+c,c=a-b,a=c+3); //a=-3 b=1 c=-4 a=-1 printf("%d\n", d); return 0; }
11.9 下标引用、 函数调用 和结构成员
[] () . -> 结构体中使用,后期介绍

12. 常见关键字
关键字 | 说明 |
---|---|
auto | 声明自动变量 |
break | 跳出当前循环 |
case | 开关语句分支 |
char | 声明字符型变量或函数返回值类型 |
const | 声明只读变量 |
continue | 结束当前循环,开始下一轮循环 |
default | 开关语句中的"其它"分支 |
do | 循环语句的循环体 |
double | 声明双精度浮点型变量或函数返回值类型 |
else | 条件语句否定分支(与 if 连用) |
enum | 声明枚举类型 |
extern | 声明变量或函数是在其它文件或本文件的其他位置定义 |
float | 声明浮点型变量或函数返回值类型 |
for | 一种循环语句 |
goto | 无条件跳转语句 |
if | 条件语句 |
int | 声明整型变量或函数 |
long | 声明长整型变量或函数返回值类型 |
register | 声明寄存器变量 |
return | 子程序返回语句(可以带参数,也可不带参数) |
short | 声明短整型变量或函数 |
signed | 声明有符号类型变量或函数 |
sizeof | 计算数据类型或变量长度(即所占字节数) |
static | 声明静态变量 |
struct | 声明结构体类型 |
switch | 用于开关语句 |
typedef | 用以给数据类型取别名 |
unsigned | 声明无符号类型变量或函数 |
union | 声明共用体类型 |
void | 声明函数无返回值或无参数,声明无类型指针 |
volatile | 说明变量在程序执行中可被隐含地改变 |
while | 循环语句的循环条件 |
12.1sizeof 操作符
sizeof 计算的结果单位是字节
sizeof不是函数,是操作符
int main() { int a = 10; printf("%d\n", sizeof(a));//4 printf("%d\n", sizeof a );//4 printf("%d\n", sizeof(int));//4 return 0; }
int main() { int arr[10] = { 0 }; printf("%d\n", sizeof(arr));//40,计算的是数组的总大小,单位是字节 printf("%d\n", sizeof(arr[0]));//4 printf("%d\n", sizeof(arr) / sizeof(arr[0]));//40 /4=10 //数组的元素个数如何计算 int sz = sizeof(arr) / sizeof(arr[0]); return 0; }
12.2区分sizeof和strlen
#include <string.h> int main() { char arr1[] = "abc"; char arr2[] = { 'a', 'b','c' }; printf("%d\n", strlen(arr1)); printf("%d\n", strlen(arr2)); printf("%d\n", sizeof(arr1)); printf("%d\n", sizeof(arr2)); return 0; }
输出结果如下:
strlen 是库函数 是求字符长度的,关注的是字符串中是否有\0,统计\0之前出现的字符个数
sizeof 是操作符 只关注占据了多大的内存空间,不关注内存中存放的数据
sizeof 返回的单位是字节
12.3关键字 typedef
typedef 顾名思义是类型定义,这里应该理解为 类型重命名。比如:// 将 unsigned int 重命名为 uint, 所以 uint 也是一个类型名typedef unsigned int uint ;int main (){// 观察 num1 和 num2, 这两个变量的类型是一样的unsigned int num1 = 0 ;uint num2 = 0 ;return 0 ;}
register 寄存器关键字,起一个建议的作用,可以加快处理的速度,但由于计算机的发展,会自行识别重要与否,从而决定![]()
12.4关键字static
12.4.1 修饰局部变量
//代码1
#include <stdio.h>
void test()
{
int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for(i=0; i<10; i++)
{
test();
}
return 0;
}
//代码2
#include <stdio.h>
void test()
{
//static修饰局部变量
static int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int i = 0;
for(i=0; i<10; i++)
{
test();
}
return 0;
}

输出结果如图 对比理解static修饰局部变量的意义。
12.4.2 修饰全局变量
//代码1
//add.c
int g_val = 2018;
//test.c
int main()
{
printf("%d\n", g_val);
return 0; }
//代码2
//add.c
static int g_val = 2018;
//test.c
int main()
{
printf("%d\n", g_val);
return 0; }

结论:
12.4.3 修饰函数
//代码1
//add.c
int Add(int x, int y)
{
return c+y;
}
//test.c
int main()
{
printf("%d\n", Add(2, 3));
return 0;
//代码2
//add.c
static int Add(int x, int y)
{
return c+y;
}
//test.c
int main()
{
printf("%d\n", Add(2, 3));
return 0;
13. #define 预处理指令 定义常量和宏
//define 定义标识符常量#define MAX 1000 // MAX 的值就是1000//define 定义宏,宏是有参数,和函数很像#define ADD(x, y) ((x)+(y))//后面括号的是内容#include <stdio.h>int main (){int sum = ADD ( 2 , 3 );printf ( "sum = %d\n" , sum );sum = 10 * ADD ( 2 , 3 );// 宏会直接替换上面的(2)+(3)) 而函数则需要调用printf ( "sum = %d\n" , sum );return 0 ;

宏和函数各有优缺点,具体暂时不谈
14.C 指针
学习 C 语言的指针既简单又有趣。通过指针,可以简化一些 C 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C 程序员,学习指针是很有必要的。
正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。请看下面的实例,它将输出定义的变量地址:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
当上面的代码被编译和执行时,它会产生下列结果:
1 2 |
|
-
什么是指针?
指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:
1 |
|
在这里,type 是指针的基类型,它必须是一个有效的 C 数据类型,var-name 是指针变量的名称。用来声明指针的星号 * 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针。以下是有效的指针声明:
1 2 3 4 |
|
所有实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,对应指针的值的类型都是一样的,都是一个代表内存地址的长的十六进制数。
不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同。
-
如何使用指针?
使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。这些是通过使用一元运算符 ***** 来返回位于操作数所指定地址的变量的值。下面的实例涉及到了这些操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//&var; //取出a的地址, // 注:这里a的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)
|
当上面的代码被编译和执行时,它会产生下列结果:
1 2 3 |
|
指针本质是地址,口头语中指的是指针变量(上面代码中的ip)
int main()
{
int a = 10;
int* pa = &a;//& 取地址操作符
*pa = 20;//* 解引用操作printf("%d\n", a);
return 0;
}
//要想知道指针变量有多大?
//指针变量存储的是什么? - 地址
//地址的存储需要多大空间,指针变量的大小就是多大
int main()
{
printf("%zu\n", sizeof(char*));//zu专门用来打印sizeof返回值
printf("%zu\n", sizeof(short*));
printf("%zu\n", sizeof(int*));
printf("%zu\n", sizeof(long*));
printf("%zu\n", sizeof(float*));
printf("%zu\n", sizeof(double*));return 0;
}
//32位机器 - 一个地址是32个二进制位,存储需要32个bit位的空间,所32位机器上,指针变量的大小是4个字节
//64位机器 - 一个地址是64个二进制位,存储需要64个bit位的空间,所64位机器上,指针变量的大小是8个字节
//取决于编出程序的大小
-
内存

15. 结构体
struct Stu{char name [ 20 ]; // 名字int age ; // 年龄char sex [ 5 ]; // 性别char id [ 15 ] ; // 学号};
// 打印结构体信息struct Stu s = { " 张三 " , 20 , " 男 " , "20120101" };//. 为结构成员访问操作符printf ( "name = %s age = %d sex = %s id = %s\n" , s . name , s . age , s . sex , s . id );//结构体变量.结构体成员//-> 操作符struct Stu * ps = & s ;printf ( "name = %s age = %d sex = %s id = %s\n" , ps -> name , ps -> age , ps -> sex , ps -> id );
