目录
C语言
是一门
通用计算机编程语言
,广泛应用于
底层开发
。C语言的设计目标是提供一种能以简易 的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语 言。 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的 C语言程序可在许多电脑平台上进行编译,甚至包含一些
嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台
。 二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制 定了一套完整的美国国家标准语法,称为
ANSI C
,作为C语言最初的标准。 C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。
其实上面的内容都不是很重要ovo,主要看下面的
C语言的第一个程序(梦开始的地方)
在程序员的心中,第一个程序都是一个叫做Hello Word的程序
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
那就很好奇了,为什么大家第一个接触到的程序都是这个呢,带着好奇,本人去搜索了一下,得到了这样的答案:
hello,world 起源
hello world的起源要追溯到1972年,贝尔实验室著名研究员
Brian Kernighan
在撰写“B语言教程与指导(Tutorial Introduction to the Language B)”时初次使用(
程序
),这是目前已知最早的在计算机著作中将hello和world一起使用的记录。之后,在1978年,他在他和
Dennis Ritchie
合作撰写的C语言圣经“
The C Programming Language
”中,延用了“hello,world”句式,作为开篇第一个程序。在这个程序里,输出的”hello,world”全部是小写,没有感叹号,逗号后有一空格。虽然之后几乎没能流传下来这个最初的格式,但从此用hello world向世界打招呼成为惯例。
有趣的是,如果你去看Brian Kernighan的
wiki
页面,他成果列表里的第一条,不是《C程序语言》,不是《UNIX编程环境》,而是看似不起眼的“hello world”。
还读到一句很有意思的话:
Hello World
是简单的,即便没有任何基础,你也可以轻松理解,但它又不是苍白的,它带有一个程序语言鲜明的特色,体现了该语言最基本的思想和特征。同样也是hello world,让人体会到第一份成功的喜悦。
希望学习编程的我们,将这一份成功的喜悦含在嘴中,一直走下去
数据类型
C语言最基本的点,数据类型,就像是一个人出生之后,定义你是男还是女的基本性别一样
数据类型主要是用来决定你的数据所展示出来的类型
char //字符数据类型(键盘上能打出来的出数字以外的都叫字符)
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点型
double //双精度浮点型
Qs:
为什么没有字符串类型?
As:
C语言中,字符串类型是由
char字符数据类型组成的数组
来表示。
数据类型的大小
#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)); //虽说int与long大小相同,但默认long大于int
printf("%d\n", sizeof(long long));
printf("%d\n", sizeof(float));
printf("%d\n", sizeof(double));
printf("%d\n", sizeof(long double));
return 0;
}
得到:
1 2 4 4 8 4 8 8
此处的大小为byte(字节)
ps:1 bit = 8 byte 1 b = 8 bit 1 kb = 1024 b 1 mb = 1024 kb 1 gb = 1024 mb
变量
变量的命名
变量的命名:
只能由
字母
(包括大写和小写)、
数字
和
下划线
( _ )组成。
不能以数字开头
。
长度
不能超过63个字符
。
变量名中
区分大小写
的。
变量名
不能使用关键字
。
//定义例子
int age = 150;
float weight = 45.5f;
char ch = 'w';
局部变量与全局变量
#include <stdio.h>
int global = 2019;//全局变量
int main()
{
int local = 2018;//局部变量
//下面定义的global会不会有问题?
int global = 2020;//局部变量
printf("global = %d\n", global);
return 0;
}
上面的局部变量global变量的定义其实没有什么问题的!
当局部变量和全局变量同名的时候,局部变量优先使用。
ps:需要注意的是,当在同一文件中引用不同源文件的变量,需要加上extern声明外部符号,例子如下:
常量
四种常量:
1.字面常量(就是字面意思)
2.const修饰的常变量(由变量变化而来)
3.由#define定义的标识符常量
4。枚举常量
//字面常量演示
3.14; //字面常量
1000; //字面常量
//const 修饰的常变量
const float pai = 3.14f; //这里的pai是const修饰的常变量
pai = 5.14; //是不能直接修改的!
//const 修饰的常变量仍具有变量的属性 (变长数组的例子)
//#define的标识符常量 演示
#define MAX 100 //define定义的常量最好大写,且最好不加分号
printf("max = %d\n", MAX);
//枚举常量演示
enum Sex
{
MALE,
FEMALE,
SECRET
};
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
//注:枚举常量的默认是从0开始,依次向下递增1的
字符串
这种由
双引号
引起来的一串字符称为
字符串字面值
,或者简称
字符串
。
注:
字符串的结束标志是一个 \0 的转义字符
。在计算字符串长度的时候 \0 是结束标志,
不算作字符串内容
。
拓展
:strlen()函数可以计算 \0 之前有多少个元素,这里可以用strlen函数去查看arr1,arr2,arr3三个函数的区别,可以发现,arr2没有加 \0 的情况下,出现了len为35,原因是strlen没有识别到\0,便会一直往下数,printf函数同理,在没有加 \0 的情况下会打印乱码,而arr1是字符串,\0 自动隐藏,arr2在数组中添加了 \0 ,故不会出现像arr2的问题。
选择语句
if语句
当if()括号内表达式满足某一条件是,执行if{}领域内语句
若不满足if()括号内条件,则执行else{}领域内语句
ps:else并非必要存在
#include <stdio.h>
int main()
{
int coding = 0; //定义一个变量coding
printf("你会去敲代码吗?(选择1 or 0):>");
scanf("%d", &coding); //输入一个值放入变量coding中
if(coding == 1) //若coding的值为1,执行if括号内语句
{
prinf("坚持,你会进入大公司\n");
}
else //若coding的值不为1,执行else括号内语句
{
printf("放弃,回家种田\n");
}
return 0;
}
循环语句
while语句
当while()括号内表达式满足某一个条件时,执行while{}领域内语句
#include <stdio.h>
int main()
{
printf("学习编程\n");
int line = 0; //定义一个变量line并初始化
while(line<=20000) //当变量line<=20000时,执行while括号内语句
{
line++; //变量line自增1
printf("我要继续努力敲代码\n");
}
if(line>20000) //如果line>20000,执行if下的语句
printf("进入好公司\n");
return 0;
}
for语句
当for循环与while差不多,区别在与他将判断前,判断,判断后的步骤全部放入括号中,便于查看
int main()
{
int a = 666;
for(int i = 0; i<10; i++) //定义一个i=0,当i小于10时,执行for括号内语句,并且i自增1
{
a += 1;
printf("%d\n",a);
}
return 0;
}
函数
函数的特点就是简化代码,方便调用
库函数
库函数是
编译器内自带的函数
,
不需要自己编辑
,但如果想要使用,需要
先调用头文件
,才可使用头文件内部的库函数,例如我想使用printf函数来打印某一数据,就需要在代码最前端引用printf的头文件 stdio.h,方式如下 #include <stdio.h>
ps:库函数查询
:https://cplusplus.com/
自定义函数
自定义函数与库函数不同的是,是由使用者
根据自己的需求而定义
的函数
自定义函数格式:
ret_type
fun_name
(
para1
, * )
{
statement;//语句项
}
ret_type
返回类型
fun_name
函数名
para1
函数参数
#include <stdio.h>
int sum( int x , int y ) //定义一个有两个整型参数x,y 叫做sum的函数,返回值为int,
{
sum = x + y ;
printf(" %d ", sum ) ;
return sum ; //返回sum值
}
int main() //定义主函数
{
int a, b ; //定义两个变量a,b
scanf("%d %d",&a, &b); //输入a,b值
sum(a, b) //调用sum函数,并且将变量a,b作为sum函数的参数
return 0;
}
使用说明:
1.自定义函数的返回值类型(ret_type)如何定义取决于该自定义函数最终返回值的类型,如上sum值返回的是整型,那ret_type就得是int类型
2.自定义函数的参数(para1,*)称为形式参数(形参),而真正放入函数中使用的叫做实际参数(实参),如上自定义自定义函数内x,y为形参,而主函数调用自定义函数传入的a,b为实参
自定义函数会根据传入实参的量去进行运算,并最终返回根据实参计算出的值
数组
C语言中给了数组的定义:一组相同类型元素的集合
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
定义一个整形数组,最多放10个元素
格式如下:
ret_type name [length] = {ele1,*}
返回类型 数组名字 [数组长度] = { 数组元素1,*}
注意:
一般而言,数组长度必须是一个常量
,但是在部分编译器上,
支持
变长数组
,可以在数组长度内放变量而不会报错,但不能初始化数组(建议查找或点击链接了解有关变长数组的概念)
数组下标
C语言规定:数组的每个元素都有一个下标,
下标是从0开始的
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
对于这个数组而言,1的下标索引值就是0,2的下标索引值就是1,以此类推
数组还可以通过下标索引值来访问相应元素
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", arr[1]);
}
这里访问数组arr下标索引为1的元素,也就是2,并将其打印
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%d\n", arr[1]);
arr[1] = 666;
printf("%d\n", arr[1]);
}
还可以通过下标索引修改对应的元素,上面代码将下标索引为1的元素,也就是2修改为666,最终重新输出会输出666
数组的输出
#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;
}
这里是通过循环遍历数组去打印数组内元素
指针
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,
每个内存单元的大小是1个字节
。 为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
QS:内存编号地址是怎么产生的?
AS:电脑具有32位与64位操作系统,可以理解为有32根电线与64根电线,电线通电有高电频与低点频,换作数字信号即为0和1,对于32位电脑来说,若有32根电线,每条电线拥有出现0和1的两种可能性,那么32根电线一共会出现 2^32 种 0和1 的排列方式,也就是会出现2^32个地址(64位则会出现2^64种),每个内存分配一个编号地址,这便是内存编号地址的产生原因。
int main()
{
int a = 10 ;
//&a 实际占据了4个字节的空间,每个字节都有地址,但是&a拿到的是第一个字节的地址
}
ps:打印地址的符号为 “
%p
”
如何存放指针地址
int main()
{
int a = 10;
int* pa = &a;
}
内存编号 = 内存地址 = 指针
pa是一个存放地址(指针)的变量,所以把 pa 叫做指针变量,pa 的类型就是int*
QS:如何理解int*
AS:以上面代码为例子,假设变量a的地址为10,那么pa存放的便是a的地址10,
而
i
nt*中的*是说明pa是指针变量,而int指的是pa指针变量存放的对象a是int类型
(& 取地址操作符)= 来
(* 解引用操作符)= 去
int main()
{
int a = 10;
int* pa = &a;
printf("%d\n", a); //输出a的值
printf("%d\n", *pa); //输出a的值(*pa==a)
printf("%p\n",pa); //输出a的地址(%p专门打印地址)
printf("%p", &a); //输出a的地址(可以通过取地址符&来输出a的地址)
return 0;
}
从上面代码可以看出各种不同的有关指针的表达方式的相同点
指针变量有多大?
指针变量用来存放地址,地址是32/64位机器上,由32/64个0和1组成的二进制序列,需要32/64bit位的空间存放,指针变量就需要4/8个字节存放
指针变量的大小取决于地址的大小
32位平台下地址是32个bit位(即4个字节)
64位平台下地址是64个bit位(即8个字节)
结构体
c语言提供了结构体
用来描述复杂对象
直接上例子
#include <stdio.h>
struct Student
{
char name[20];
int age;
char id[15];
float score;
};//分号必须存在
//以上为声明结构体类型
int main()
{
struct Student s1 = { "阿强",19,"2022212010",99.5f };//创建结构体对象s1
struct Student s2 = { "阿珍",19,"2022010212",99.5f };//创建结构体对象s2
//struct Student s3;
return 0;
}
通过struct修饰,声明一个结构体类型(结构体包含的元素类型)
再在头函数中创建以该结构体类型为框架的结构体的对象s1,s2
输出结构体
通过
结构体对象 . 成员
的方法输出
printf("%s %d %s %f\n", s1.name, s1.age, s1.id, s1.score);//打印结构体s1的内容
printf("%s %d %s %f\n", s2.name, s2.age, s2.id, s2.score);//打印结构体s2的内容
通过
指针结构体解引用 . 成员
的方法输出
加括号的原因是(*ps)需先解引用s1的地址
struct Student * ps = &s1;
printf("%s %d %s %f\n", (*ps).name, (*ps).age, (*ps).id, (*ps).score);//通过结构体指针打印s1内容
通过
指针结构体 —>操作符 成员 的方法输出
struct Student * ps = &s1;
printf("%s %d %s %f\n", ps->name, ps->age, ps->id, ps->score);//效果同上,表达方式不同