C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易 的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
计算机语言的发展
低级 -> 高级
机器语言 ->助记符,汇编语言 -> B -> C
标准ANSI C 变换过程:ISO K&R C89/C90 C98 C99
C语言和其他语言的区别
C语言是一门面向过程的计算机编程语言,与 C++, Java等面向对象的编程语言有所不同。
C语言编译器
常见的C语言编译器有Clang、Gcc、WIN - TC、SUBLIME、MSVC、Turbo C等。
#include
{
printf(“hello world\n”);
return 0;
}
主函数的标准格式
//推荐
int main()
{
}
//古早写法
void main()
{
}
//不规范写法
main()
{
}
//不推荐但正确的写法
int main(void)//详细告诉你这个函数没有返回值
{
}
科普
返回值
C语言中有一个约定,返回 0 表示正常返回,返回的是非 0,表示的是异常返回。
printf
如果想在屏幕上打印数据,可以使用printf库函数,printf是一个C语言编译器提供的库函数。库函数使用要包含头文件.
通用单位
计算机处理数据,处理的为二进制数据。
1 bit 存一个二进制位
1 byte = 8 bit 1 KB = 1024 byte 1 MB = 1024 KB 1 GB = 1024 MB TB ZB
数据类型
为什么写代码?是为了用程序解决问题。
数据类型符号
数据类型
单位
char
字符数据类型
1个字节
short
短整型
2个字节
int
整型
4个字节
long
长整型
4个字节
long long
更长的整型
8个字节
float
单精度浮点数
4个字节
double
双精度浮点数
8个字节
sizeof用法
sizeof是操作符,sizeof计算单位的结果是:字节 - byte。
sizeof(long) >= sizeof(int),也就是说long长整形只要大于等于int整形就可以了,在vs2022中计算出long的大小为4个字节。
计算方法
#include
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));
printf("%d\n",sizeof(float));
printf("%d\n",sizeof(double));
return 0;
}
//编译结果:
// 1 2 4 4 8 4 8
生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)
有些值是可变的(比如:年龄,体重,薪资)
不变的值,C语言中用常量的概念来表示,变的值在C语言中用变量表示。
int age = 150;
float weight = 45.5f//加f原因:编译器默认为double类型。如果想定义为float类型,就加上f
char ch = ‘w’;
1)只能由字母(包括大写和小写)、数字和下划线(_)组成。
2)不能以数字开头。
3)长度不能超过63个字符。
4)变量命中区分大小写的。
5)变量名不能使用关键字。
变量分为两种类型,一种为全局变量,一种为局部变量。
局部变量适用于局部范围内,全局变量适用于全局范围,在整个项目中都有效。
局部变量与全局变量的定义
#include
int global = 10;//全局变量
int main()
{
int local = 1;//局部变量
return 0;
}
小思考
下列代码有没有问题,若没有问题输出的值是什么:
#include
int num1 = 2019;//全局变量
int main()
{
int num1 = 2020;//局部变量
printf("num1 = %d\n",num1);//打印结果是什么?
return 0;
}
在vs2022中编译结果如下:
因此我们可以得出:当局部变量和全局变量同名的时候,局部变量优先使用。
变量的使用
#include
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;
}
作用域
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的而限定这个名字的可用性的代码范围就是这个名字的作用域。
1)局部变量的作用域是变量所在的局部范围。
2)全局变量的作用域是整个工程。
生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。
1)局部变量的生命周期是:进入作用域生命周期开始,出作用于生命周期结束。
2)全局变量的生命周期是:整个程序的生命周期。
理解
对于作用域和生命周期,如果光看定义可能很难理解,接下来anduin就用一个例子来帮助我们更好地理解这个概念,生命周期可以看做从anduin从出生到死亡这个范围,但是作用域呢可以看成auduin可以坚持写代码的时间,当我的作用域结束之后,我的生命周期并没有结束。这两个是不同的两个概念。
字面常量
就是直接写出的常量值如 30,3.14,“abcdef”,'a’等等…
const 修饰的常变量
#include
int main()
{
const int num = 100;
num = 200;//报错
return 0;
}
当我们对num进行二次赋值是发生报错,这是因为 const 修饰的变量无法被重新写入。
那么常变量又是什么,我们怎么理解他呢?
num 本质是变量,但是因为 const 的修饰限定了他的改变, 就和常量一样。
如果想更加深入理解关键字 const 可以参考我的一篇博客http://t.csdn.cn/PtuDv
#define 定义的标识符常量
#include
#define MAX 1000
int main()
{
int a = MAX;
printf("%d\n", a);
//MAX = 2000;//报错
int arr[MAX];//可以
return 0;
}
当我们对MAX进行二次赋值时,发生报错,这可以看出MAX为常量。
但是#define 定义的标识符常量可以用来定义数组元素个数如int arr[MAX];
由于#define起替换作用,这里的数组相当于int arr[1000];
枚举常量
枚举从字面意思上看就是一一列举,生活中很多东西都可以一一列举,它们都可以用枚举来表示。
代码演示:
enum Sex
{
MALE,
FEMALE,
SECRET
};
int main()
{
enum Sex s = SECRET;
printf("%d %d %d\n", MALE, FEMALE, SECRET);//0 1 2
MALE = 3;//报错 证明
}
我们编译后发现在对枚举定义MALE进行赋值时报错,所以我们可以得出结论在枚举类型enum Sex中列举出的可能取值都是枚举常量。而枚举常量中首个元素被默认初始化为0,在进行打印时,打印结果为0 1 2。枚举常量中的状态值是呈+1式递增的。
Tips:枚举常量的初始状态值可以被改变,输出的枚举常量都是数字!!!
我们在键盘上敲出来的所有东西都可以理解为字符,字符一般用单引号’ '来表示。
字符的使用
#include
int main()
{
char ch = ‘a’;
ch = ‘x’;
printf(“%c”, ch);
return 0;
}
字符的本质:ASCII码值
ASCII码值小科普
计算机中存储,表示都是二进制的,早期科学家们,为了区别字符,给每个字符都编了号,这个编码就称为ASCII码值。
Tips:常见的一些ASCII码值我们可以把它背下来,如0 - 48,a - 97, A - 65等等…
字符串是什么
这种由双引号引起来的一串字符称为字符串字面值,或者简称字符串。(“hello anduin.\n”,“a”," "这些都是字符串)。
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
字符串的使用
#include
int main()
{
char arr[] = “abcd”;
printf(“%s\n”,arr);
return 0;
}
隐藏的’ \0 ’
#include
int main()
{
char arr1[] = “abcd”;//此处可以结合内存来说明
char arr2[] = {‘a’, ‘b’, ‘c’, ‘d’};
return 0;
}
接下来我们启动调试,查看arr1,arr2的内容。
在arr1的结尾处隐藏着一个’\0’作为结束字符串的标志,但是arr2中却没有’ \0 '。
’ \0 ’ 的威力
别看上述例子只是少了一个’ \0 ‘,在这里’ \0 '并不是摆设,它也是有自己的“威力”的。
在我们用代码看它的作用之前让我们先了解一下strlen函数。
strlen是一个库函数,在使用时需要引用头文件#include
函数作用:用来求字符串长度。
#include
#include
int main()
{
char arr1[] = “abcd”;
char arr2[] = {‘a’,‘b’,‘c’,‘d’};
printf(“%d\n”,strlen(arr1));
printf(“%d\n”,strlen(arr2));//可以画图详细讲解
}
这里的输出结果是什么???让我们开始运行,我们看到结果如下:
我们不禁产生疑问,34是哪来的?原来这都是’\0’一手导致的。
分析:’\0’仅仅是字符串结束的标志,在统计长度时,并不会加上\0一起计算
故输出arr1的长度为4,由于arr2中没有\0,在求字符串由于\0并没有出现,所以便一直向后计算,直到遇到\0,这里面的长度也是包含了我们之前出现的烫烫烫的个数的!!!
所以’\0’的威力还是很大的。
小思考
如何输出这个路径?D:\Anduin_code\anduins-code-warehouse
这样可以吗?
int main()
{
printf(“D:\Anduin_code\anduins-code-warehouse”);
//输出结果:D:Anduin_codenduins-code-warehouse
}
但当我们运行之后,发现我们并不能输出我们的路径,这是为什么?因为这里\和其他字符构成转义字符。
转义字符,通俗点来讲就是在所有ASCII码前都可以用\加数字来表示,如\0,\t,\n等等,都可以被称作为转义字符。转义字符顾名思义就是转变意思。
下面我列出了一些转义字符:
转义字符
释义
?
在书写连续多个问号时使用,防止他们被解析成三字母词
’
用于表达字符常量
"
用于表示一个字符串内部的双引号
\
用于表示一个反斜杠,防止他被解释为一个转义序列符
\a
警告字符,蜂鸣
\b
退格符
\f
进纸符
\n
换行
\r
回车
\t
水平制表符
\v
垂直制表符
\ddd
ddd表示1 - 3个八进制数字。如:\130x
\xdd
dd表示2个十六进制数字。如:\x30 0
让我们用代码了解他们都是什么作用(详情见注释):
int main()
{
printf("%s\n","(are you ok??)");//在老编译器上会打印(are you ok]
//三字母词:??) ->]
printf("%c\n",'\'');//输出结果为:'
printf("%c\n","\"");//输出结果为:"
printf("\a\a\a");//蜂鸣,电脑叫三声
char a[] = "abc";
printf("%c%c\b%c", a[0], a[1], a[2]);//输出结果为:ac(\b为退格符,b被删掉)
printf("1\t23");//输出结果为:1 23(\t是水平制表符,八个空格)
printf("anudin\n");//输出结果为:anduin且换行
printf("%c\n",'\130');//输出结果为:X (1*64+3*8+0*1 = 88 也就是字符 X)
printf("%c\n",'\x30');//输出结果为:0 (3*16+0*1 = 48 也就是字符 0)
}
小测验
看到这儿大家应该对转义字符有一定的理解了,接下来就用几道题目来测验一下自己吧:
题1:如何正确输出代码路径:D:\Anduin_code\anduins-code-warehouse?
题2:这个路径的长度是多少?
#include
int main()
{
printf("D:\\Anduin_code\\anduins-code-warehouse?");
printf("%d\n",strlen("D:\Anduin_code\anduins-code-warehouse"));
return 0;
}
揭晓答案:
注释的作用
1)代码中不需要的代码可以直接删除,也可以注释掉。
2)代码中代码比较难懂,可以加注释文字。
注释风格
#include
int main()
{
//printf("hello anduin\n");C++注释风格 推荐
/* C语言风格注释 不推荐
printf("oops!\n");
*/
}
C语言注释风格由于*总是和更近的*/进行匹配,从而导致无法嵌套注释,所以我们一般还是用C++风格的注释。
我们的生活处处都有选择,在C语言中也不例外,存在着选择语句。
举一个比较简单的例子:如果你坚持好好学习,那么以后可能会收获一份好offer。
但是如果你不好好学习,那你可能会被社会淘汰。
代码演示:
int main()
{
int studying = 0;
printf("你会坚持每天学习吗?(1 or 0):>");
scanf("%d",&studying);
if(studying == 1)
{
printf("好offer在等着你!\n");
}
else
{
printf("竹篮打水一场空!\n");
}
对于你,你会怎么选择呢?是选择1 好offer,还是选择 0 竹篮打水一场空呢?
anduin这里还是建议大家努力起来,一起加油!
当然分支语句可不仅仅是这么点,我们今天只是了解,等之后会我会重新整理的。
有些事必须一直做,比如我们日复一日的学习敲代码。
这也就形成了一种循环,C语言中有一种语句叫做循环语句,我们接下来就来了解一下它,循环语句分为三种:
while语句
for语句
do…while语句
我们今天就重点看一下while语句,其他两种循环语句,我会在以后详细讲解:
while(表达式)
循环语句;
我们可以通过一个例子来了解一下while语句是如何进行的,比如你坚持写代码,当你代码写到两万行时,你可能觉得你的水平差不多了,也可以找个offer了,那么这个循环也就随之结束。如下面代码所示:
#include
int main()
{
int line = 0;
printf("insist codeing >\n");
while(line < 20000)
{
printf("写代码\n");
line++;
}
if(line == 20000)
{
printf("好offer\n");
}
return 0;
}
编译运行结果为:(因为这里代码过多就截取一小部分)。
如何理解
在我们学习数学的时候,也学过函数,它们表示为f(x),C语言中也存在着函数。
程序中存在main函数,那么除了main函数可不可以编写其他的函数呢?可以!!!
函数的结构
实现Add函数
#include
int Add(int x,int y)
{
return (x + y);
}
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
scanf("%d%d",&num1,&num2);
sum = Add(num1,num2);
printf("%d\n",sum);
}
分析:用sum来接受Add函数所返回的值的同时调用Add函数,于是num1和num2在进行Add函数计算后,返回值为num1 + num2的值。
为什么使用函数
想象一下,如果这边有很多组数据要想加,使用平时的思路,我们需要初始化很多次,代码冗长,不美观,效率低,但是如果我们封装一个函数,可以达到事半功倍的效果。
如果要存储1-10的数字,怎么存储?
使用数组。
C语言中给了数组的定义:一组相同类型元素的集合
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//定义一个整形数组
char ch[5] = { 0 };//对char类型数组不完全初始化,其中元素默认被初始化为0
char ch2[] = {‘a’,‘b’,‘c’};//这样也正确
char ch3[] = { 0 };//正确,元素个数为1个,元素为\0
C语言规定:数组的每个元素都有一个下标,下标是从0开始的。
数组是通过下标来访问的。
代码演示:
#include
int main()
{
int arr[5] = { 1, 2, 3, 4, 5};
printf("%d\n",arr[3]);//访问下标为3的元素
//printf("%d\n",arr[10])//不可以这样访问!!!
}
请注意数组不能越界访问,例如:arr[10]就越界访问了!!!越界访问可能会导致程序崩溃,程序出错等严重后果。
设想一下:你在一层楼中买了两套房子,但是你自己的房子不住,偏偏要去住别人的房子,这是什么,这就是非法访问,严重的是要被抓起来了,就说明你违法了!!!所以越界访问的危险可见一斑。
#include
int main()
{
int arr[10] = { 0 };
//0~9
//输入10个值给数组
int i =0;
while(i<10)
{
scanf("%d",&arr[i]);
i++;
}
//输出数组的10个值
i = 0;
while(i<10)
{
printf("%d ",arr[i]);
i++;
}
return 0;
}