导言:
本文章会带你基本了解C语言,对他有一个感性的认识,对其有一个框架,后期在对其进行更加细致的补充。
C语言是啥呢?
C语言就是人和机器交流的语言,早起人与计算机交流使用2进制(科研人员),后面在简化有了汇编(部分极客),在有了B语言,C语言(大众普及),到现在C++/java…,C语言就是一个编程语言与计算机沟通实现你的想法的语言
在C语言/C++中一般在IDE(集成开发环境)中创建项目都会默认出现下面的代码
int main()
{
return 0;
}
//或者是
int main(int argc,char *argv[])
{
return 0;
}
//这里的argc 和 argv是命令行参数,argc是有多少个指令 argv就是指令啦,挖坑。
或许有人第一次见到会有这样的疑惑:这是啥?有啥用?能吃吗?疑问3连。幸好你遇到了我,解释如下:
main 函数是程序得入口,也就是运行的必经之路。你或许以为他就是这样,
但是他还有许多的坑或者说细节:一个项目中只能有一个main函数,一个项目只能有一个main函数,一个项目只能有一个main函数重要的事情说三次
,如果你写了多个会咋样
那当然是报错喽,运行不起来。
变量简单来说就是用来存储数据的,且变量的类型不止一个,有内置类型,和自定义类型。那你或许会问为啥需要类型,如果抽象成现实生活中事情,那就是买房子,每个人的需求不一样买的房子也不一样,但是造房子有对应的户型,当然是你也可以买地皮自己造.......当然计算机也是创建变量本质也就是向内存申请空间
//内置类型
// sort(短整型)、int(整型)、long(长整型)、long long(长长整型) 、char(字符型)、float(单精度浮点型)、double(双精度浮点型)
//sizeof是一个关键字,也是一个操作符,计算变量的大小(字节)
printf("%d",sizeof(short)) //sort 和short int result: 2字节
printf("%d",sizeof(int)) // result:4
printf("%d",sizeof(long)) // result:4
printf("%d",sizeof(long long)) //result:8
printf("%d",sizeof(char)) //result:1
printf("%d",sizeof(float)) //result:4
printf("%d",sizeof(double)) //result:8
//自定义类型
//struct 所定义的变量,现在感性理解他就是内置类型的集合体
//union 联合体
//变量类型大小涉及到特殊存储规则,挖坑
有人会问为啥用的是字节呢?字节是啥?
如图所示计算机的单位与换算:
那么为啥是字节呢?
因为计算机只识别0101的二进制序列,那数据存储也是以二进制存储到内存中,那么按照上图所示,当然是字节为好,byte少了kb又太多
,你想一个栈区(变量等存放的地方)也就4mb(看操作系统),如果kb的话工程大都不够创变量了~
拓展ASCII表
简单理解,看作用域(就是变量可以使用的范围),或者说生命周期(就是变量创建到销毁的范围)如下代码
int global; //全局变量
int main()
{
int local;//局部变量
return 0;
}
//全局变量:从创建到程序结束才释放
//局部变量:从创建到花括号/大括号({})结束,但是可以用static修饰导致他出了作用域爷不会销毁,挖坑
有趣的例子/特性
#include
int a =1;
int main()
{
int a = 2;
printf("%d",a);
return 0;
}
那你觉得答案是:(1,2)呢?
如果你选的是2那么恭喜你选对了,那为啥呢?既然你真心诚意的问了,我就大发慈悲的告诉你吧。这个就是局部优先的原则,全局变量和局部变量重名时局部优先。
但是我不建议你在平时写这样的代码,不过这个会在题目中出现,插个眼。
人如其名,创建后就不能改变,如果改了则会报错,在C语言中有以下方式创建
#include
int main()
{
//1.字面常量
10;
//2. const所修饰的常变量,后面和指针数组结合会有奇怪的化学反应
const int a; int const a; //俩者一致
//3. 宏定于的标识符常量
#define MAX 100;
return 0;
//4.枚举类型就是一一可以列举的值,可以理解给数字起名字,如下代码Read默认从0开始后面依次递增,也可以赋值赋值后已赋的常量为起点依次递增
enum 类型
{
Read,
Green,
Blue
}
}
不知道你是否有个疑问那就是别的都是常量,为啥const修饰的叫做常变量呢?
//在C11标准之前创建数组只可以用常量,数组就是同类元素的集合
const int count = 10;
int arr[count]; //这样就会报错
字符串就是一串由 一对双引号所引起的多个字符(“ ”)
,且字符串的终止表示就是\0
,如下所示
资源管理器验证:
用代码验证
从sizeof那里可以看出a2比a1多一个元素,但是你看strlen的字符串长度a2远比a1长,strlen也是以\0位终止,没有则会一直找\0
转义字符:
不知到大家在用printf 和 scanf (输入,输出库函数) 的时候有没有想过为啥要引用头文件呢?
库函数就是使用频率非常高,则官方自己实现方便我们使用。
为啥要引用头文件,因为当你在编译的时候会自动吧头文件中所包含的代码(库函数)全部拷贝到当前文件。
拓展
// 当你使用函数的时候是从上往下查找的后实现的代码写到下面去如下所示
int add(int x , int y);
int main()
{
prinft("%d",add(10,20));
}
int add(int x , int y)
{
return x+y;
}
在日常生活中我们一直都在选择和重复做某事,当然在编程中选择就是分支,重复就是循环,使用如下代码
// 分支
//单分支 if/else if/ else
//多分支 switch
if(条件)//条件真则执行语句1
语句1;
else//条件假执行语句2
语句2;
if(条件1)//条件1真则执行语句1
语句1;
else if(条件2)//条件1假且条件2真则执行语句2
语句2;
else//条件1且条件2都是假则执行语句3
语句3;
//当switch的值和case值一样时则执行对应的语句,如果都不满足且有default则执行default中的语句
switch(值)
{
case 值1:
语句1;
case 值2:
语句2;
case 值3:
语句3;
default:
语句4;
}
//循环
//while
while(条件) //当条件满足时会一直循环执行语句不满足时候则退出循环
{
语句;
}
//for:一般用于已经知道循环多少次
for(变量;条件;退出条件)
{
语句;
}
do
{
语句;
}while)(条件); //do while无论条件是否满足都会执行语句
循环和分支都可以使用的关键字:
int main()
{
for(int i=0;i<10;i++)
{
if(i ==5)
{
continue;
}
printf("%d ",i);
}
//result:0 1 2 3 4 6 7 8 9
for(int i=0;i<10;i++)
{
if(i ==5)
{
break;
}
printf("%d ",i);
}
//result:0 1 2 3 4
}
在学编程有一个梗,我最讨厌的写注释和别人不写注释。那注释的用处是啥呢? 就是给你和别人理解代码。C语言注释的方式
/**/的好用技巧:当你实现了一个函数时企且有许多参数时,你可以这样给参数进行注释:
int add(int x/*参数1*/,int y /*参数2*/)
{return x+y;}
int main()
{
add(10,20);
}
同类型的一组变量的集合,语法如下
// 类型 + 数组名 + [数组变量个数] = {数据}
int arr[10];
特殊的语法:在C11版本之前的版本数组创建定义个数一定要是常量,不
可以是变量,一定要是常量
请问如何访问 和 给变量放入变量呢?
//[](下标访问操作符) 或者 *数组名+值
//注意,下标是从0开始的一定要记住,不然就越界访问了
int arr [10];
for(int i =0;i<=10;i++)
{
arr[i] = i;
printf("%d ",arr[i]);//result:0 1 2 3 4 5 6 7 8 9
}
for(int i =0;i<=10;i++)
{
printf("%d ",arr+i);
}
static的作用
//static 会改变局部变量的生命周期
int fun1()
{
int a = 0;
a++;
printf("%d ",a);
}
int fun2()
{
static int a = 0;
a++;
printf("%d ",a);
}
int main()
{
for(int i =0;i<3;i++)
fun();
}
//result fun1: 1 1 1
//result fun2: 1 2 3
但是或许会有这样的场景,在多人开发时A1写了个add的函数但是他的功能是俩数相加在加1,A2后面在开发别的功能想要用add函数但是他想要的就是简单的俩数相加,他偷懒声明看看有没有如果有
,那么这不就出大麻烦了嘛,所以static修饰一下则可以避免这样的乌龙。
//算数操作符
printf("加:%d",1+2); //3
printf("减:%d",1-2); //-1
printf("乘:%d",1*2);//2
printf("除:%d",1/2);//0
printf("取模:%d",1%2);//1,取余数
//除法在这里是向下取整,并不是小数,但是只要除数和被除数其中一个是小数则结果也是小数
//取模俩边一定是整数不然会报错
//移位操作符(移动的是存储的二进制位,如上所述每个值在底层存储都是以二进制存储的,然后其实简单理解就是二进制位向左/右移动)
printf("左移:%d",1<<2); //2
printf("右移:%d",1>>2); //0
//8进制位例子
00000001 >> 1 = 00000000
//位操作符
printf("加:%d",1&1);// 1,对应的二进制位都是1时则保留,其余都为0
printf("加:%d",1|0); //1,对应的二进制位只要一个是1就为1
printf("加:%d",1&0); //0,对应的二进制位不同时则保留
//8进制位例子
00000001 | 00000001
& --->000000000 | & --->00000000
00000001 | 00000000
//单目操作符
printf("! %d",!0001); // 0 ,逻辑反,非零数值变零,零变1
printf("sizeof %d",sizeof(int)); // 4,计算大小,也就是字节数
printf("前后置++/-- %d",++1); //2 就是自增或者自减,后置则为 1 先输出在加减
printf("~%d" ,~0001);//-2,全部二进制位取反
int a =10;
printf("& %p",&a);//0xadada 取地址,取出a在内存中的地址/编号
printf("* %d",*(&a)); //10 解饮用,就是拿着地址去找对应的值
//逻辑操作符
printf("&& 与 %d",1&&1); // 1 ,逻辑与,操作符俩边都要是真的则为真
printf("|| 或 %d",1||0); //0 ,逻辑或,操作符俩边只要一个是真的则为真
//条件操作符/三目操作符
printf("%d",1>2?1:2); // 2 ,语法格式 a>b:a:b a>b真则为a反之b
其实就是用#define定义的函数,一般都是常用简短的函数.
#define ADD(X,Y) X+Y
int add(int x,int y)
{
return x+y;
}
int main()
{
printf("%d",add(1,1)); // 2
printf("%d",ADD(1,1));// 2
}
虽然他们的结果都是一样,但是宏的效率更高,那是为啥呢?
拓展:内存(简单理解)
如上所述,创建变量就是向内存申请一块空间,那么你想如何在内存中找到你的变量呢?
如何创建和使用一个指针呢?
//类型 * 变量名
int a =10;
int *pa = &a;// pa此时存的就是a的地址
printf("%d",*pa);//用解引用操作符则可以找到a的值
那么一个指针大小是多少呢?
printf("%d",sizeof(int *));
printf("%d",sizeof(char *));
printf("%d",sizeof(short *));
//结果都是4
为啥结果都是4字节呢?
这个就是电脑位数有关了,如果你是32位的电脑则电脑有32根地址,每根地址线通电则会产生0/1俩中结果,那么32个位来表示地址的话那么刚好就是4字节,对应的64位就是8字节