本文旨在大概讲述C语言中的一些基本语法,在编者后面的文章中会详解,仅以参考。
什么是C语言 C语言是一种结构化的程序设计语言,用于底层开发,C语言的设计目标是能提供一种能以简易的方式编译,处理低级存储器,产升少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
于今为止我们讨论的语法都是基于C89/C90的国际标准。
目前主流的编译器有:Clang、GCC、MSVC、SUBLIME…
1.如何执行? 答:C语言是从主函数的第一行开始执行的
此外特别注意,main函数只能有一个,一个工程可以有多个.c,但多个.c只能有一个main函数(.c是C语言编写的文件后缀)且每一个后缀为.c的源程序都可以单独运行。
2.问C语言中的三种基本结构? 答:顺序,分支(选择),循环(重复)
3.问C语言中,程序的基本组成单位是? 答:函数,包括main()其他函数和函数
int main() //main函数是C语言代码的入口,main是函数名,int表示main函数的返回类型
{
return 0; // return--返回
// { } 叫函数体
}
注:底层的编译运行原理,编者会在后期着重讲解。
练习:在屏幕上打印“C语言”字样
#include//头文件是stdio.h int main() { printf("C语言");//printf()是库函数,对于使用库函数需要引用头文件 return 0; }
在MSVC编译器下,如果控制台不显示,可以通过:右击项目,点击属性->配置属性->链接器->系统->子系统后面一项->选择控制台。
注意:
1.C语言中带#号的指令并不是C关键字的一部分,不属于C语言。
- #include指令就是告诉编译器看到这句话就要把我写的文件包含进来
- #define指令就是告诉编译器看到这个宏就用前面以经定义好的内容替换。
ps : 关键字(是c语言内置的,可以直接用)后面会详解。
数据类型1.什么是数据类型? 答:数据类型是数据的一个属性,它告诉编译器或解释器程序员打算如何使用数据。
| 数据类型 | 数据大小 | 类型含义 |
|---|---|---|
| char | 1 byte | 字符数据类型 |
| short | 2 byte | 短整型 |
| int | 4 byte | 整型 |
| long | 4 byte | 长整型 |
| long long | 8 byte | 更长的整型 |
| float | 4 byte | 单精度浮点型 |
| double | 8 byte | 双精度浮点型 |
| 注: |
- 此处的长短整型后面会讲解,此时仅需要明白长短是表示可取到的范围
- C语言中没有字符串类型,与Python不同,不能混淆
- long在x64机器上是8byte。
2.数据类型如何在C语言中使用
int main()
{
char ch = ' a ' ;// 注意这里是单引号
printf(" %c n " , ch) ;// n是换行操作符
int age = 20 ;
printf(" %d n" , age) ;// 此句表示在屏幕上打印出 age 这个变量的内容即 20
short num = 20 ;
float weight = 55.5 ;
double d = 0.0 ;
return 0 ;
}
int main()
{
//sizeof - 是关键字,不是函数 - 也是操作符 -- 作用是用来计算类型或变量所占空间的大小
printf(" %d n " , sizeof(char) ) ;
printf(" %d n " , sizeof(short) ) ;
printf(" %d n " , sizeof(int) ) ;
printf(" %d n " , sizeof(float) ) ;
printf(" %d n " , sizeof(double) ) ;
printf(" %d n " , sizeof(long) ) ;
printf(" %d n " , sizeof(long long) ) ;
return 0 ;
}
问1:sizeof的单位是什么?
答 :sizeof的单位是字节-byte
问2 : long为什么没有比int更长?
答: C语言标准中,sizeof(long)>=sizeof(int)即可,当前编译器采用的就是=的情况。
问3:为什么要分这么多的整型类型?
答:short和long在内存中所占的空间大小不同,为了节省空间,可以用适合的数字存放在合适的地方,不会浪费空间,能提高利用率。而且多种数据类型也能更加丰富的表达生活中的各种值。
bit - 比特位,是计算机中的最小单位,二进制的0,1 在内存中就分别占了1bit。
byte - 字节,1byte = 8bit
kb = 1024 byte
mb =1024 kb
gb =1024 mb
tb = 1024 gb
pb = 1024 tb
答:计算机通电后,有正负极的电子,就代表着1和0
注意(多注意以下,用多了就会了):
1.比如’a’表示字符常量,在内存中占一个字节,‘a’+1就表示’a’的ascii码+1,就是’b’。
2.比如"a"表示字符串常量,在内存中占两个字节,因为最后还有一个结束符号’ ’,“a”+1表示指针运算,结果就指向结束符’ ’。
变量:可变的数据,如生活中的工资,年龄,体重。
常量:不可变的数据,如血型,性别,圆周率。
int main()
{
//创建一个变量 : 类型 变量的名字 = 0(=0是初始化);
int age =20;
double weight = 75.3;
age = age + 1;
weight = weight - 10;
printf("%dn" , age ) ;
printf("%lfn" , weight ) ;
return 0;
}
变量的分类
- 局部变量
在大括号{}内部定义的量都属于局部变量 - 全局变量
在大括号{}外部定义的量都属于全局变量
int a = 100;
int main()
{
int a = 10 ;
printf("%dn" , a ) ;//结果为10,局部优先,当然,我们应当避免出现相同名字
int b = 0 ;
int c = 0 ;
scanf("%d %d", &b , &c ) ;//sancf函数是输入函数,&叫做取地址操作符,后期会重点讲解
retrun 0;
}
练:输入两个数,求和并打印
int a = 100;
int main()
{
int a = 10 ;
int b = 0 ;
int sum = 0 ;
scanf("%d %d", &a , &b ) ;//sancf函数是输入函数,&叫做取地址操作符,后期会重点讲解
sum = a + b ;
print("%dn" ,sum);
retrun 0;
}
注:scanf()函数不安全,在MSVC中会报出错误,其中会显示_CRT_SECURE_NC_WARNINGS字样,我们可以在文件首行加入#define _CRT_SECURE_NC_WARNINGS 1(1表示开启)。
问:如何永久保存使scanf()一直可用?
答:在安装路径下找到VC->vcprojectitems(找不到可以直接用everything搜索)->newc++.file.cpp->用记事本打开后保存#define _CRT_SECURE_NC_WARNINGS 1 这句话。
局部变量的作用域:自己所在的大括号{}内,出{}即销毁。
全局变量的作用域:整个工程。
注意:如果在另一个.c文件中定义了全局变量,在其他的.c文件中如若要使用,则需要声明变量
//声明一下变量
extern int g_val; //extern是声明的关键字
int main()
{
printf("%dn" , g_val ) ;
retrun 0;
}
生命周期
局部变量的生命周期是:进作用域生命周期开始,出即销毁
全局变量的生命周期是:整个程序的生命周期
- 字面常量
不常用但存在
int main(){ 3.14 ; 10 ; 'a' ; "abcdef" ; retrun 0;}
- const修饰的常变量
int main(){ //const修饰的常变量 const int num = 10 ; //num = 20 ; 当const加上之后,num就变成的常变量 - 具有常属性(不能被改变的属性) printf("%dn", num) ; retrun 0 ;}
int main(){ int arr[10] = { 0 } ;//10个元素 const int n = 10 ; int arr1[n] = { 0 } ;//error,n是个常变量,本质还是变量,只不过被const修饰,具有常属性,[]里必须是常量才行 return 0;}
- #define定义的标识符常量
#define MAX 1000 //无分号,后期define定义的宏文章中会着重讲解,此句在main()里面定义也行int main(){ int n = MAX ; printf("n= %dn" , n ) ; return 0;}
- 枚举常量(enum)
一般用于可以一一列举的常量
enum Sex{ //枚举类型的变量的未来可能取值 MALE, //枚举常量可以初始化,下面所打印出来的值也一一改变 FEMALE, SECRET//最后一个无逗号}int mian(){ enum Sex s =MALE ; //MALE = 3 error 枚举常量不能更改 printf("%dn" , MALE ) ;// 0 printf("%dn" , FEMALE ) ;// 1 printf("%dn" , SECRET ) ;// 2 return 0;}
字符串+转义字符+注释
字符串
字符串就是一串字符,用双引号引起的一串字符,其结束标志是
字符串的末尾隐藏了一个 的字符
证明 的存在:
注意:char arr = " abcd " ;此写法是错误的,字符里不能有字符串,只能是数组中存放一串字符
int main(){ //字符数组 - 数组是一组相同类型的元素 char arr[] = "hello" ; char arr1[] = "abc" ;// 存在 a b c char arr2[] = { 'a' , 'b' , 'c' } ;// 存在 a b c printf("%sn",arr1);// 能找到 ,字符串正常打印出abc printf("%sn",arr2);// 不知道什么时候出现在内存中,所以abc后面会出现乱码,因为 才是结束的标志,没遇到不结束 retrun 0 ;}
练习: 求字符串长度
#include转义字符int main(){ //求一下字符串的长度 int len = strlen("abc") ;//strlen函数的头文件是string.h printf("%dn",len);//3 -- 不算在字符串长度中,一直计算到 之前,如果求arr2就是个随机值 return 0;}
在C语言中为了防止被转义
printf("c:\test\test.c");//这里的两个\被解析成一个,才能避免t被单独转义
以下仅列举重要的转义字符
| 转义字符 | 释义 |
|---|---|
| ’ | 为了显示 ’ |
| " | 为了显示" |
| 为了显示 | |
| a | 警告字符,电脑会响一声 |
| n | 换行 |
| r | 回车 |
| t | 水平制表符–键盘上的Tab键 |
| ddd | ddd表示1~3个八进制的数字,如:130 X |
| xdd | dd表示2个十六进制的数字。如:x30 0 |
重点1:ddd
ddd表示的是3个数字
1.八进制的130转换为十进制的88,
2.X在ASCII中的值就是88,所以会出现 X
问:为什么会有ASCII表
答:为了在计算机上存储符号,比如@,#,¥,A,B,C给他们每一个都有一个对应的ASCII码值
重点1.1 xdd
printf("%cn" , 'x30' ) ;// 十六进制转换为十进制后是48 所对应的ASCII码值为0printf("%dn" , strlen("c:test328test.c"));//14个字符,t一个,32一个
选择语句
if…elif…else语句
int main(){ if (coding == 1) { printf(1); } elif (coding ==2) { printf(2); } else { printf(3); } retrun 0;}
循环语句
while()语句
int main(){ int line=0; while(line<10) { printf(1); line++; } return 0;}
函数
C语言中有多种库函数,也可以自定义函数
int Add(int x , int y)//自定义函数,返回类型为整型{ //此处的x ,y为形参 int z = 0; z=x+y; return z;}int main(){ int num1 = 0 ; int num2 = 0 ; scanf("%d %d" , &num1 , &num2 ) ; int sum = Add( num1 , num2 ) ;//num1 , num2为实参 printf("%dn" , sum ) ; return 0 ;}
注:形参和实参的定义和注意事项后期会讲解。
数组 数组的定义:1. 问:如果要存储1-10的数字,怎么存? 答:C语言中给了数组的定义:一组相同类型元素的集合
int arr[10] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 } ;//定义了一个整型数组,最多放10个元素
数组的使用
数组是一组相同类型元素的集合
char ch[5] = { ' a ' , ' b ' , ' c ' } ;//{}里只有3个元素,ch这是不完全初始化,其余默认都为0
数组的访问
用下标来访问
int main(){ char ch[5] = { ' a ' , ' b ' , ' c ' } ; printf("%dn" , ch[1]);//打印出b return 0;}
操作符
操作符有多类
算术操作符+ - * / %
- / 号
//对于整数而言int a = 9 /2 ;printf("%dn" , a ) ;//只显示4,只得到商4,没有小数float a =9 / 2;//因为 / 号两端都是整数,所以算出的也是整数printf("%fn" , a ) ;//结果是4.000000不是4.5float a =9 / 2.0 ;//此时就打印了4.5printf("%fn" , a ) ;
- % 号(取模/取余)
int a = 9 % 2 ;printf("%dn" , a ) ;// 打印出1
位移操作符
>> <<
左移操作符<<,右移操作符>>移动的是二进制位
位操作符& ^
&按位与 | 按位或 ^ 按位异或
赋值操作符单目操作符= += -= /= &= |= >>= <<=
只有一个操作数的就是单目操作符
例:a+b — + 就是双目操作符
!a— ! 就是单目操作符
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置–,后置–
++ 前置++,后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
注意:sizeof是操作符不是函数,作用是计算类型或者变量的大小
int arr[10] = { 0 } ;printf("%dn",sizeof(arr)) ;//40 4*10 -- 4是每一个元素的所占的大小printf("%dn",sizeof(arr[0])) ;//4 -- 首元素的所占大小int sz = sizeof(arr) / sizeod(arr[0]) ;// 10 ---通过sizeof算出数组个数
拓展1:~操作符
按位取反,操作二进制,即把二进制中数字,1变成0 , 0变成1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WmK2TOQq-1650871880691)(https://gitee.com/mr-kimi/cloudmagess/raw/master/img/Z6KJKEMU{_M{A6GPLSC]J.png)]
ps:具体的原反补解释,请读者详阅编者的其他文章,有详解
逻辑操作符条件操作符&& 逻辑与
\ 逻辑或
逗号表达式exp1 ? exp2 : exp3
- 逗号表达式的运算过程为:从左往右逐个计算表达式。
- 逗号表达式作为一个整体,它的值为最后一个表达式(也即表达式n)的值。
练习:(a = 3,b = 5,b+ = a,c = b* 5),求逗号表达式的值? 答案:40。
常见关键字[] () . ->
C语言中的关键字:
- C语言提供的,不能自己创建关键字
- 关键字不能做变量的名字
auto break case const continue default do double else enum extern float for goto if int long register short signed sizeof static switch typedef union unsigned void volatile while
注:
1. auto一般加在变量前,但一般会自动省略,auto 在新的C语言语法中也有其他的用法
2. register寄存器关键字 在定义的变量前加上,表示建议变量的值放在寄存器中(推荐大量,频繁的数据变量添加寄存器关键字,可提高效率)
3. signed有符号位,二进制最左位
4. unsigned 无符号位
5. union联合体(共用体)
6. typedef类型重定义,简便理解就是把一个类型换个名字用改名后的当做类型来定义
7. static 静态的
特别强调:
1. define(预处理指令) , include(预处理指令)不是关键字
2. static修饰局部变量,改变了局部变量的声明周期(本质上改变了变量的存储类型)
3. static修饰的全局变量,使得该全局变量只能在当前.c文件中使用(本质上是把全局变量的外部链接属性改为内部链接属性),static修饰函数效果与全局变量相同
define是一个预处理指令
- define定义符号
#define MAX 1000 int main() { printf("%dn" , MAX) ;//打印出1000 return 0; }
- define定义宏
#define ADD(X,Y) X+Yint main(){ printf("%dn",ADD(2,3));//宏---直接替换,后面的文章会讲解原理 return 0;}
指针
指针是C语言中的最重要部分,指针精通,C语言精通,但指针不稳定,因为它能直接操作内存
如果要介绍指针,那么不得不先介绍一下计算机中的内存
电信号转化为数字信号,32个bit有2^32次方种排列,每个排列都可以当做编号。这个编号就被称为内存单元的地址
-
x32电脑中有2^32次方个内存单元
-
一个内存单元有多大空间?
假设我们一个内存单元占1 bit
那么2^32次方个就是4294967296bit
除8就是536870912byte
除三次1024就是0.5GB。这就有点太小了
为了多管理内存,我们规定一个内存单元就是一个字节byte
拓展1:
问:我们生活中常说的电脑是32位机器还是64位机器,这32和64代表着什么呢?
答:32位机器也就是由电脑里的32根地址线(物理上的线),它通电后+电荷就是1,-电荷就是0,我们把这种正负电荷的电信号转换成数字信号,就是0/1组成的二进制序列。
此外注意一点,指针能存放自己的地址,但代码会报出警告错误,如果读者愿意尝试调试的话,会发现此时存放的地址和指针地址是相同的,内存中已经放进去了----特别注意,这种写法本身是错误的,编者只是发现了这种现象,分享给你们,切记不能记混
结构体是C语言中特别重要的点,结构体使得C语言有能力描述复杂类型
比如:描述一个学生对象(学生名字,性别,年龄,学号)
struct Stu{ char name[20]; int age; char sex; char id[15]}int main(){ struct Stu s={"张三",20 , "男" , 123 } ;//结构体的创建和初始化 printf("%s %d %s %d" , s.name , s.age , s.sex , s.id ) ; struct Stu *ps =&s; printf("%s %d %s %d" , (*ps).name , (*ps).age , ps->sex , ps->id ) ; return 0;}
小结
本篇文章讲解了C语言的大纲,仅做读者参考和复习排错。敬请斧正。
作者:@kimi



