前言
原本打算是上一年写C语言这个系列的,由于本人比较懒,再加上学校的事比较多,所以就拖到了现在,前段时间是想着不更新这部分内容的,不过总感觉学的不踏实,缺了点什么,
所以打算利用10余天时间把C语言系列更新完,和大家一起学习进步!!!
话不多说,直接开卷(本篇会概述一下C语言的各个语法,后面细讲)
什么C语言?
C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台
C语言是一种面向过程的编程语言,与java,c++等面向对象的编程语言有所不同。
数据类型
char //字符数据类型
short //短整型
int //整形
long //长整形
long long //更长的整形
float //单精度浮点数
double //双精度浮点数注:C语言中有字符串类型嘛?
C语言中没有字符串类型,C++中有
每种类型的大小
这里我简单拓展下,
bit 比特
byte 字节 =8bit
kb 1024byte
mb 1024kb
gb 1024mb
tb 1024gb
pb 1024tb
想更深入的了解其中的关系和取值范围,可以看我写的计算机组成原理.
变量和常量
生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等)
有些值是可变的(比如:年龄,体重,薪资).
不变的值,C语言中用常量的概念来表示,变得值C语言中用变量来表示。
定义变量的方法
int age=150;
float weight=45.5f;
char ch='w';
变量的分类
- 局部变量
- 全局变量
int a = 2022;//全局变量 int b = 2021;//全局变量 int main() { //test1(); //思考一下a等于哪个值? int a = 2023;//局部变量 printf("%d\n", a); printf("%d", b); return 0; }
知识加油站
全局变量:在函数外定义的变量;使用范围:从定义开始到本源文件结束;
局部变量:在一个函数内定义的变量;使用范围:定义该变量的函数内
简单了解
1.使用全局变量会占用更多的内存(因为其生命期长),不过在计算机配置很高的今天,这个不成为什么问题,除非使用的是巨大对象的全局变量,能避免就一定要避免。
2.使用全局变量程序运行时速度更快一些(因为内存不需要再分配),同样现在也快不了多少。
3.全局变量全部存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放。
4.局部变量可以和全局变量重名,但是局部变量会屏蔽全局变量。在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。根据使用范围来区分的。
变量的作用域和生命周期
作用域
作用域,程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域.
1.局部变量的作用域:变量所在的局部范围
2.全局变量的作用域:整个工程
生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
1.局部变量的生命周期:进入作用域生命周期开始,出作用域生命周期结束.
2.全局变量的生命周期:整个程序的生命周期
int main() { { int c = 20; } printf("%d", c); return 0; }
常量
C语言中的常量分为以下几种:
- 字面常量
#include<stdio.h> int main() { 3.14;//字面常量 2021; return 0; }
- const修饰的常变量
#include<stdio.h> int main() { const int a=10;//const修饰的常变量 //const修饰的能修改嘛? a=50; return 0; } //结果:不能修改,左值指定const对象
- #define定义的标识符常量
#include<stdio.h> #define MAX 100//标识符常量 int main() { printf("%d\n",MAX); return 0; }
- 枚举常量
enum Sex { //初始化 MALE=5, FEMALE=12, SECRET }; int main() { enum Sex s; //未初始化;从0开始依次增长 printf("%d\n", MALE);//0 printf("%d\n", FEMALE);//1 printf("%d\n", SECRET);//2 //可以直接赋值嘛?:不可以但是可以初始化 MALE = 5;//不可以 //初始化后的值 printf("%d\n", MALE);//5 printf("%d\n", FEMALE);//12 printf("%d\n", SECRET);//13 return 0; }
字符串
“hello bit.\n"
这种由双引号引起来的一串字符称为字符串面值,或者简称字符串.
注:字符串的结束标志是一个\0的转义字符.在计算字符串长度的时候\0是结束标志,不算作字符串内容。
int main() { char arr1[] = "bit"; char arr2[] = { 'b','i','t' }; char arr3[] = { 'b','i','t','\0' }; printf("%s\n", arr1); printf("%s\n", arr2); printf("%s\n", arr3); return 0; }
第二个没有\0也就是结束标志,所以会出现"烫烫烫"这些字;
我们来测试一下,字符串长度
a2中没有\0就没有结束字符,所以会出现随机数;
a1数字是5,说明\0不算进字符串内容
我们这里拓展一下,sizeof
sizeof把\0算进字符串长度中,strlen则不算入;
strlen 是一个函数,它用来计算指定字符串 str 的长度,但不包括结束字符(即 null 字符)。其原型如下面的代码所示:
size_t strlen(char const* str);
也正因为 strlen 是一个函数,所以需要进行一次函数调用,调用示例如下面的代码所示:
1. char sArr[] = "ILOVEC"; 2. /*用strlen()求长度*/ 3. printf("sArr的长度=%d\n", strlen(sArr));
很显然,上面示例代码的运行结果为 6(因为不包括结束字符 null)。这里需要特别注意的是,函数 strlen 返回的是一个类型为 size_t 的值,从而有可能让程序导致意想不到的结果,如下面的示例代码所示:
/*判断一*/ if(strlen(x)>= strlen(y)) { } /*判断二*/ if(strlen(x)- strlen(y)>= 0) { }
从表面上看,上面的两个判断表达式完全相等,但实际情况并非如此。其中,判断表达式一没什么问题,程序也能够完全按照预想的那样工作;但判断表达式二的结果就不一样了,它将永远是真,这是为什么呢?
原因很简单,因为函数 strlen 的返回结果是 size_t 类型(即无符号整型),而 size_t 类型绝不可能是负的。因此,语句“if(strlen(x)-strlen(y)>=0)”将永远为真。
关键字 sizeof 是一个单目运算符,而不是一个函数。与函数 strlen 不同,它的参数可以是数组、指针、类型、对象、函数等,如下面的示例代码所示:
char sArr[] = "ILOVEC"; /*用sizeof求长度*/ printf("sArr的长度=%d\n", sizeof(sArr));
相对于函数 strlen,这里的示例代码运行结果为 7(因为它包括结束字符 null)。同时,对 sizeof 而言,因为缓冲区已经用已知字符串进行了初始化,其长度是固定的,所以 sizeof 在编译时计算缓冲区的长度。也正是由于在编译时计算,因此 sizeof 不能用来返回动态分配的内存空间的大小。
转义字符
假如我们想打印一个目录:c:\code\test.c\n
我们一般会这样写:
int main() { printf("c:\code\test.c\n"); return 0; }
运行结果却是:
这里就不得不提一下转义字符了。转义字符顾名思义就是转变意思。
下面看一些转义字符。
转义字符 | 释义 |
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\' | 用于表示字符常量' |
\“ | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。 如: \130 X |
\xdd | dd表示2个十六进制数字。 如: \x30 0 |
我这里只举几个常见的,大家感兴趣可以下去试试
int main() { int a = 4, b = 6; printf("%d\n", a);//换行 printf("%d\t%d\n", a, b);//水平制表符 printf("%c\n", '\'');//用于表示字符常量 printf("%s\n", "\"");//用于表示一个字符串内部的双引号 return 0; }
思考题:
#include <stdio.h> int main() { printf("%d\n", strlen("abcdef"));//6 // \32被解析成一个转义字符 printf("%d\n", strlen("c:\test\328\test.c"));//14 return 0; }