前言:
1.初学习了c语言,感觉还是很不错的,哈哈~~。下面让我来分享下我目前对c的认识
题外:后面有关于c语言风格培养的《高质量的c-c++编程》PDF版链接,有需要自拿。哈哈~~。
一.初识c语言
1.1计算机语言的发展过程:由需求促进发展,由不成熟逐渐成为流行。
早期的科学家通过数字1和0的组合控制硬件计算机的运行。后来在需求下,人们创建了助记符(汇编语言).但还是不能满足需求,于是B语言出现,再后来高级语言C,c++,java等相继出现。但不同地方语言规范不同,为消除这种交流障碍,促进语言的融洽,1989年,ANSI(美国国家标准协会)制定了一套c语言规定(c89),1990年,国际标准化组织(IOS)也制定了一套规定(c90).1999年,ANSI/IOS(C9X委员会)联合委员会共同制定了c99;2011年,C9x发布了(C11)标准。至此C语言成为世界流行语言。目前使用较多的是c89/c90(2个几乎等同), |
1.2什么是c语言?
c语言是一种面向过程的计算机编程语言,广泛用于底层C语言的设计目标 是提供一种 能简易编译,处理低级存储器,产生少量机器码以及不需要任何运行环境支持便能运行的编程语言。 |
选择C语言的理由:流行性,高效性,可移植性高,强大而灵活,面向程序员。
1.流行性:c是一门流行语言。其融合了计算机科学理论和实践的控制特性。便于用户完成自顶向下的规划,结构化编程和模块化设计。使得c语言编写的程序更易懂,更可靠。 |
2.高效性:c是高效的语言。c语言具有通常汇编语言才有的微调控控能力,可以根据具体情况一获得最大运行速度,最有效的使用内存。 |
3.可移植性高:c是可移植的语言。我们知道不同操作系统其运行方式不同。而我们想在不同系统运行c程序,需要我们在少量更改程序的条件下,仍能运行c程序。这必然要求我们的语言可移植性高。而在这些语言中,c语言崭露头角,其可移植性非常高 |
4.强大而灵活:许多操作系统,如UNIX系统大部分也是通过c语言编写的。另外很多程序编译器,解释器也是用c语言编写的。 |
5.面向程序员:c语言的强大,可以清晰的让程序员简洁的表达自己的想法与意图。 |
简单的c程序
#include
int main()
{
printf("helloworld!");
return 0;
}
据说在业界能这句话能给你的编程之旅带来好运!你好世界! |
三.c语言的语法规则
3.1 c中的数据类型:整形,浮点型,字符型及其所占空间大小
整型 |
名字 |
int |
(普通整形), |
short (int)可以省略(int) |
短整形 |
long |
长整形 |
long long |
更长的整形 |
unsigned int |
无符号(—)整形(只能为正) |
signed int |
有符号整型(一切整数) |
浮点型: |
名字 |
float |
单精度浮点数型 |
double |
双精度浮点型 |
3.1.2 每种数据类型的在内存中的大小
补充:
1.sizeof(类型) |
1.它是运算操作符,不是函数 |
2.它用于测定数据在内存中的字节(byte)大小,字符串结束标志‘\0’也要被计算内存。 |
2.strlen(字符数组名) |
1.它是函数,不是操作符。 |
2.它用于测定字符数组长度。在测定长度时以’\0’为字符串结束标志。 |
3.字节(byte)
计算机的单位:
内存单位 |
名字 |
补充 |
bit |
比特 |
计算机最小内存单元 |
byte |
字节 |
1byte=8bit |
kb |
|
1kb=1024byte |
mb |
|
1kb=1024kb |
gb |
|
1kb=1024mb |
tb |
|
1kb=1024gb |
pb |
|
1kb=1024tb |
我们知道计算机能识别的机器语言(二进制语言)(一定顺序的1/0),而对于每个二进制1/0在内存中都要占有一定的空间,我们规定每个这样的1/0所占的空间为1bit(计算机中的最小内存空间)。而计算机中的数据是按字节,分配空间的,即认为1byte为运行时的内存单元。 |
01000100 占用1个字节空间(8个bite位) |
而对于数据类型我们规定:
类型 |
内存大小 |
整型(int) |
4个字节(32bite位) |
短整形(short) |
2个字节(16个bite位) |
long long型 |
8个字节。 |
类型 |
内存大小 |
字符型 |
一个字节(8个bite位)。 |
类型 |
内存大小 |
单精度型(float) |
4个字节(32个bite位) |
双精度型(double) |
8个字节(64个bite位)。 |
==另外c语言规定:sizeof(long)>sizeof(int)=4;具体long型所占字节大小,依据不同编译器结果不同。 |
3.2变量,常量
3.2.1.变量:可以随时改变的量(数据).如:年龄,身高等;
3.2.2.常量:不能改变的量(数据)。如:圆周率,血型等。
3. 2.3定义变量的方式:
数据类型+自定义数据名称+初始化+语句结束标志“;”(分号)
初始化依据条件可以不进行初始化。
如 年龄是整形数据
身高是浮点型数据
字母是字符型数据
int age=19;
float length=170f;
char a='w';
3.2.4变量的使用:
#include
int main()
{
int age=19;
float length=170f;
char name[]="***";
printf("年龄=%d\n",age);
printf("长度=%f\n",length);
printf("名字=%s",name);
return 0;
}
3.2.5变量的分类
局部变量:
定义在一对{}内的变量都是局部变量,无论是main函数还是普通函数。 |
全局变量:
注意
当全局变量与局部变量冲突时,遵从“局部变量优先原则” |
3.2.6变量的作用域与生命周期————有效使用变量
局部变量:
1.作用域:在所创建位置的一对{}内的任何地方都可以使用: |
2.生命周期: |
局部变量自创建的一对{}始,到出这对{}为止,这段时间为其生命周期;** |
right:
a创建于最外面的{},所以main函数内的任何地方都可以使用。 |
a创建于里面的{},所以里面{}内的任何地方都可以使用。 |
error
思考
#include
int main()
{
{
int a=1;
printf("%d\n", a);
}
printf("%d\n", a);
return 0;
}
#include
int main()
{
int a = 1;
{
int a=1;
printf("%d\n", a);
}
printf("%d\n", a);
return 0;
}
全局变量: |
1.作用域:自创建到程序结束的任何地方都可以使用。 |
2.生命周期:自创建到程序结束为其生命周期。 |
3.2.7常量:
1.字面常量:血型,名字等
2.const修饰常变量(一旦const就不可更改):
#include
int main()
{
const int a=19;
a=22;//变量一旦const就不可更改,重新赋值。
printf("%d",a);
return 0;
}
3.#define定义的标识符常量
注意
1.define定义的宏常量不占用内存,它只会傻瓜式的语言替换。 |
分析:
结果并不是20,而是12的原因是:t=x+2*2; |
4.枚举常量
当一个变量的所有可能都可知的情况下,我们常定义枚举常量;如性别,数据类型等 |
c语言规定:枚举常量中的第一个常量在数值上是0,其它依次加1。如果人为的初始化第一个常量,其它常量任然依次加1.** |
3.3字符与字符串+转义字符+注释;
3.3.1.字符与字符串:
字符:像‘w’这种由一对‘ ’所引用的字符。
字符串:”name“像这种用一对” “所引用的连续字符,称为字符串。
因为c语言中没有字符串型数据,因此我们用字符数组定义字符串;
3.3.2.转义字符:
补充:
1.在计算机中,为了方便字符型与实型数据间的运算,我们人为的规定每个字符对应的一个十进制数。为此我们制定了ASII表 |
注意
常用转义字符:‘\n’,’\t’,’\ddd’,’\xdd’; |
注意
3.3.3.注释
1.在c程序中我们想解释自己的程序时,我们常使用“//”; |
2.在c程序中我们想保留部分程序,不让其起作用时, |
注意
3.4 c语言的3种结构:顺序,选择,循环。
3.4.1顺序:一步一步执行代码。
3.4.2选择结构(分支语句):
注意
3.4.2.1 if语句
1.if语句的2种形式
第一种
if(表达式){语句体}
else 语句体
第二种
if(表达式){语句体}
else if(表达式) {语句体}
…
else 语句体
注意
1.我们规定else与最近的if匹配. |
2.注意if语句体中的关键字break,continue; |
看题
#include
int main()
{
int a = 0;
int b = 2;
if(a == 1)
if(b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
思考这题的输出结果
答案:
什么都不输出思考注意中的第一点
2 .switch语句:
1.switch语句的形式
switch(整形表达式)
{
case 整形常量表达式:语句;
…
}
注意
1.switch中的整形表达式不可以为浮点型数据,但可以为,枚举类型(可以当作是整形常量),字符型数据(计算机在碰到字符新数据时会将它自动转化为整形进行运算)(图一) |
2.case 中的必须为整形常量,或者是枚举类型(枚举也看以看作是一种特殊常量) |
3.switch中的关键字break是用于分开语句块的。且不能使用关键字continue;(图二) |
4.当执行的case没有break作为跳出switch时,其会==,默认==继续执行下面的case,直到再次遇到break;(图三) |
5.虽然switch中的default是默认选项的意思,但使用时多留意其前面是否有break;再次体现第三点的重要性(图四) |
6.default 可以放在switch语句体内的任意位置 |
看图
图一
图二
图三
图四
问题
#include
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)
{
case 1:
n++;
case 2:
m++;
n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d, n = %d\n", m, n);
return 0;
}
答案:
分析:(1)-》(2)-》(3)-》(4)-》(5)
(1)先执行外面的swtich,n为1,执行case 1,后m=3.因为其后无break,进行执行case。 |
(2)执行case 2-》m=3,n=2. |
(3)执行case 3->,执行内嵌的switch中的case 2-》m=4,n=3,遇到break,跳出内部switch |
(4)执行case 4-》m=5.遇到break,跳出外部switch; |
(5)m=5,n=3; |
3.4.3循环结构:while,do while,for循环;
1.while语句形式
while(表达式){语句体}
当表达式为真是,执行语句体.
2.do …while语句形式
do{语句体}while(表达式);
先执行语句体,后判断表达式
3.for语句形式
for(表达式1,表达式2,表达式3)
表达式1:
表达式1为初始化部分,用于初始化循环变量的。
表达式2:
表达式2为条件判断部分,用于判断循环时候终止。
表达式3:
表达式3为调整部分,用于循环条件的调整。
注意
1.while的执行条件始终比循环体多一次。 |
2.do while语句注意语句结束要有分号"";“,且其循环体始终与表达式执行次数一致。 |
3.brake只能跳出一层循环(当内循环结构时,只能跳出内部一层循环结构) |
4.continue只能跳出本次循环。 |
练一练
打印9*9乘法表
for()形式
int main()
{
int i = 0;
int j = 0;
for (i = 0; i < 10; i++)
for (j = 1; j <= i; j++)
{
printf("%d*%d=%-2d", i, j, i * j);
if (j == i)printf("\n");
}
return 0;
}
分析:通过i控制行,j控制列.
while形式
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
int main()
{
int i = 1;
int j = 0;
while (i < 10)
{
j = 1;
while (j <= i)
{
printf("%d*%d=%-3d", i, j, i * j);
j++;
}
printf("\n");
i++;
}
return 0;
}
分析:外层循环控制行,层控制列
do while形式
int main()
{
int i = 1;
int j = 0;
do
{
j = 1;
do
{
printf("%d*%d=%-3d", i, j, i * j);
j++;
} while (j <= i);
printf("\n");
i++;
} while (i<10);
return 0;
}
分析:外层循环控制行,层控制列
3.5函数
背景:在一个main函数中,我们可以通过代码的形式完成某些目的,但是这样,main函数就会变得很长。为了尽可能的减少main函数的代码长度,我们创建函数来完成这部分工作。 |
函数形式:
返回值类型+函数名+(形参1,形参2,…)
#include
int add(int x,int y)
{
return x+y;
}
int main()
{
int a = 0;
int b = 0;
int c = 0;
scanf("%d%d",&a,&b);
c=add(a,b);
printf("%d\n",c);
return 0;
}
函数声明形式:
返回值类型+函数名+形式类型+”;“
#include
int main()
{
int add(int x,int y);
int a = 0;
int b = 0;
int c = 0;
scanf("%d%d",&a,&b);
c=add(a,b);
printf("%d\n",c);
return 0;
}
int add(int x,int y)
{
return x+y;
}
注意
1.自定义的函数要有返回值. |
2.自定义的函数可以放在main函数的前面,或者后面(在后面的时候,要在main函数中提前声明)。 |
3.实参传递数据到形参时,参数类型要相同,不然会丢失部分数据。 |
3.7数组
背景:如果我们想存储一组数,我们一个怎么办呢?这时候即需要c中的数组; |
3.7.1数组的定义:
数组元素类型+数组名+【数据数量】;
int arr[10]={
1,2,3,4,5,6,7,8,9,10};
3.7.2数组下标:
int arr[10]={
1,2,3,4,5,6,7,8,9,10};
数组长度是10,下标从0~9;
3.7.3数组的使用
#include
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.数组下标小于数组长度,且其最大值为数组长度-1; |
2.数组名是数组的首地址; |
看题
下面程序有问题吗?
#include
int main()
{
int i = 0;
int arr1[10]={
0};
char arr2{
10}={
0};
char arr3[10]={
'0'};
printf("%d\n",arr1[0]);
printf("%c\n",arr2[0]);
printf("%c\n",arr3[0]);
return 0;
}
分析:
arr1[0]被初始化为0;arr2[0]被初始化为0;arr3[0]被初始化为字符’0’; |
0 对于int 型 就是数字0,但对char ,在ASII表中是 空 的意思,即没有任何意义(NULL)。 |
字符’0’对于char 型是字符串结束标志。 |
|
3.8操作符
3.8.1算术操作符:
+,-,*, /,%
注意
除法的2种情况: |
/的前后都是整形数据时,对结果取整。 |
/的前后存在浮点数时,结果就是浮点数。(图一) |
#include
int main()
{
int a =0;
int b =0;
int c2 =0;
float c2 =0;
scanf("%d%d",&a,&b);
c1=a/b;
c2=a/b;
printf("%d\n",c1);
printf("%f\n",c2);
return 0;
}
3.8.2位移操作符:
<<,左位移操作符
>>右位移操作符
它们移动的是补码
补码补充
1.计算机在内存中处理数据,都是按数据的补码形式进行运算的,最后以原码的形式表现数据。 |
2.正数与0的,原码,反码,补码是一样的。 |
3.负数的原码是按正数编时的二进制原码;反码是原码除符号位,其它位取反;补码是反码+1。 |
题目
#include
int main()
{
int a=-1;
int b=-1;
printf("%d\n",a<<2);
printf("%d\n",b>>2);
return 0;
}
3.8.3位操作符:&,|,^
注意
运算符 |
功能 |
运算规则 |
& |
按位与 |
对应位均为1时,才位1,否则为0 |
| |
按位或 |
对应位存在1时就为1 |
^ |
按位与或 |
对应位相同为0,相异为1 |
<< |
左移 |
补码左移若干位,超出丢弃(不包括1),剩下补0,每左移一位,相当于多乘2; |
>> |
右移 |
补码右移若干位,正数左补0,负数左补1,右边溢出丢。 |
3.8.4赋值操作符:=,+=,-=,*=,/=,&=,|=,<<=,>>=
3.8.5单目操作符:
单目操作符表
单目操作福 |
功能 |
! |
逻辑反操作 |
- |
负值 |
+ |
正值 |
& |
取地址 |
sizeof |
就类型长度(以字节为单位) |
~ |
对一个数的补码按位取反 |
– |
前置:先自减,后应用;后置:先应用,后自键 |
++ |
前置:先自增,后应用;后置:先应用,后自增 |
* |
间接访问操作符(解应用操作符) |
(类型) |
强制类型转换 |
3.8.6关系操作符:
>,>=,<,<=,==,!=;
3.8.7逻辑操作符(双目运算符):
逻辑操作符 |
功能 |
&& |
且,只有当2边逻辑都为真是才为真 |
|| |
或,一边为真即为真 |
3.8.8条件操作符
3.8.9逗号表达式:
exp1,exp2,exp3…
注意
逗号表达式的运算结果以最后一项为准。
看图
3.8.10下标引用[],函数调用(),结构体成员->.
3.9关键字
关键字 |
功能 |
auto |
存储类别说明关键字(局部变量) |
break |
终止一层循环 |
case |
swtich语句中的case |
char |
字符数据类型说明关键字 |
const |
将变量定义为长量 |
continue |
结束本次循环,直接执行下次循环 |
default |
switch语句中,当没有满足case的情况,默认执行default语句 |
do |
do {}while();语句中的关键字 |
double |
双精度数据类型说明关键字 |
else |
与最近if匹配的else分支语句 |
enum |
枚举变量的说明关键字 |
extern |
提前告知变量,函数等出现在别的文件中 |
float |
单精度数据类型说明关键字 |
for |
for的说明关键字 |
goto |
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。 |
if |
分支语句说明关键字 |
int |
整形数据说明关键字 |
long |
更大整形说明关键字 |
return |
返回某种类型的值,结束函数 |
short |
短整形说明关键字 |
signed |
有符号型说明关键字 |
sizeof |
测定数据占内存空间的大小,单位字节 |
static |
静态成员说明关键字(具体说明看下面) |
struct |
结构体说明关键字 |
switch |
swtich分支语句关键字 |
typedef |
重新定义数据类型别名:typedef unint unsigned int |
union |
联合说明关键字 |
unsigned |
无符号整形说明关键字 |
void |
空类型说明关键字 |
while |
while语句说明关键字 |
register |
|
volatile |
|
注意
在定义变量,函数名时不能使用关键字
3.9.1static:
1.修饰局部变量:延长局部变量生命周期,不改变其作用域(图一) |
2.修饰全局变量:改变全局变量的外联性(可被其它文件使用。extern),使全局变量只能被本模块使用。 |
3.修饰函数:改变函数的外联性(可被其它文件使用。extern),使函数只能被本模块使用。 |
图一
图二
图三
3.10#define定义宏常量和宏
#define+“空格”+宏常量名+常量 |
#define+“空格”+宏名+表达式 |
3.11指针
3.11.1内存:
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。 |
3.11.2内存是怎么被编号的?
我们知道32位计算机有32根物理地址线(通过地址线,寻找相应地址的数据),在通电时,每根电信号被转化为1/0。而这样的32跟地址线,可形参232种不同的32为位二进制编码。二232字节换算成G时为4G,在32为系统4G内存足够了。因此以这 232种二进制(其实是将二进制转化为16进制,编号内存的)为编号刚好,(另外通过增加地址线的方法,可以增加内存) |
3.11.3地址的存储
3.11.4指针变量:
3.11.5指针的大小:
前面我们知道,32系统下的32为地址线,通过32位二进制编号内存,所以在内存中我们存储一个地址时需要4个字节的内存单元,即32位下指针大小为4字节。同理64位系统下,指针大小为8字节 |
3.11.6补充
我们在定义变量时,随机存储在内存中。当程序结束时,变量内存释放。每次运行,变量都随机存储于内存中。 |
3.12结构体
前言
对于人这个抽象概念,我们很模糊,但我们具体到某个人时,他的名字,性别等,做为他的具体属性被我们知道。 |
因此我们定义结构体,用于对具有共同属性的一类事物的抽象 |
3.12.1结构体定义:
struct+结构体名
{
属性1;
属性2;
…
};
注意
1.定义结构体不可丢关键字struct |
2.结构结尾的分号不能丢 |
3.12.2结构体数组:
| ------------------------------------------------------------ |
感言:
1.对目前c语言的有些地方学的不深,不敢过多描述。哈哈。
2.在这段学习中,我会了一些小游戏,由其是关机程序,贼有意思!哈哈。后面会补上的。
3.《高质量的c-c++编程》PDF版链接:链接:https://pan.baidu.com/s/1yW6FgsZDqeOtVzePrdZk_Q
提取码:2021