【C语言】初始C语言

【C语言】初始C语言,第1张

什么是C语言

C语言是一门通用计算机编程语言,广泛应用于底层开发。


C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。



尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。



二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。


目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。



C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。



其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。


第一个C语言程序
#include 
int main()
{
    printf("Hello World\n");
    return 0; 
}

C语言能够把执行某个特殊任务的指令和数据从程序的其余部分中分离出去,使其单独成为一个程序块,我们通常称之为函数,并取一个函数名。


这些程序块就是函数体,独立的函数(程序块)可以在程序其余部分中用其函数名多次重复使用(函数调用)。



函数的定义由多个部分构成,其一般格式如下:

返回类型 函数名 (形参声明) //函数头
{
    函数体;              //一条或多条C语句
}

一般函数都会返回一个值(return后面跟随的值),这个返回值的数据类型就是函数的返回类型。


也有一些函数没有返回值,只是执行一些具体的 *** 作(比如打印输出等),这些没有返回值的函数在定义时其返回类型为 void 型。



main( ) 函数代码片段中的“int”是指 main( ) 函数返回值的类型是整数。


计算机在运行程序时,正是通过检查 main( ) 函数的返回值来判断程序是否运行成功的。


如果让 main( ) 函数返回整数 0,就表明程序运行成功,如果让它返回其他整数值,就表示程序在运行时出了问题。


  1. C语言是从主函数的第一行开始执行的,所以C语言代码中得有main函数——入口
  2. 一个工程中main函数有且仅有一个
  3. printf是C语言提供的库函数,用于在屏幕上打印信息
  4. 使用了库函数,就得引用头文件stdio.h
数据类型

C语言程序中有 3 种数据:
一种是数字,例如,0、100、-123、1.23、3.14159、-99.9等;
一种是字符,例如,‘A’、‘z’、‘5’、‘0’、’+’、’*’、’%’、‘真’、‘假’、‘大’;
还有一种是字符串,例如,“ABC”、“china”、“C语言”、“main”、“12+3”。


C语言中的字符(character)是计算机能够表示的任意一个字符,并且必须用’ '(单引号)括起来。



C语言中的字符串(string)是多个字符的组合,必须用" "(双引号)括起来。


不同的数据在计算机中的处理方式(输入、输出及存储)是不一样的,因而在计算机编程中通常把需要处理的数据根据其处理方式的不同分为不同的组,我们把这样的分组称为数据类型。


C语言中最常用的数据类型有 3 种。


  • 整型:处理整数值(不含小数位)的数据类型。


    例如:0、1、100、9999、-123。


  • 浮点型(实型):处理浮点值(含小数位)的数据类型。


    例如:1.23、3.14159、-99.9。


  • 字符型:处理一个字符的数据类型。


    例如:‘A’、‘z’、‘5’、‘0’、’+’、’*’、’%’、‘真’、‘假’。


下表列出了 C语言中常用数据类型的取值范围和占用内存的字节数。


类型名(C语言命令符)说明字节取值范围
char字符型1其十进制代码范围为 -128~127 的 256 个字符
int整型2-32768~32768(-215 ~215-1)
long int长整型4-2147483648~21474883647(-231 ~231-1)
float单精度浮点型4+3.4 ×1038(小数点后 6~7 位有效数字)
double双精度浮点型8+1.7×10308(小数点后 6~7 位有效数)n2
  • 1字节(byte)=8比特(bit)
  • 存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。


变量常量

生活中的有些值是不变的(比如:圆周率,性别,身份z号码,血型等等),有些值是可变的(比如:年龄,体重,薪资)。



不变的值,C语言中用常量的概念来表示,变的值C语言中用变量来表示。


定义变量的方法

C语言中的变量在使用之前必须先定义。


定义变量时,我们要给变量取一个独一无二的名字,同时还要说明该变量中可以存放“什么数据类型的数据(值)”。


也就是说,一个变量中只能存放一种与其相同类型的数据(值)。


定义为存放整型数据的变量中是不能代入一个字符(字符型)或者小数(浮点型)的。


#include 
int main()
{
    int myScore,id;                 //定义两个整形变量
    long int distance=1800000;      //定义长整型变量并代入初始值
    char myName='方',job='Q';       //定义两个字符型变量并代入初始值
    float average=86.5;             //定义单精度浮点型变量并代入初始值
    double pi=3.1415926536;         //定义双精度浮点型变量并代入初始值
}
变量命名规则

变量是通过变量名区分的,所以每个变量都应该取一个与众不同的名字。


在 C语言中,给变量取名有一些特殊的规定(命名规则)。


  1. 不可以数字开头
  2. 不可包含特殊字符
  3. 不可用保留字
  4. 不可使用相同的名字

在 C语言中,有一些字(英文单词)具有特定的含义(在 C语言的某个命令符中使用了等等),不能用于其他用途,也就不能用它来做变量的名字。


我们称这些特殊的字为C语言的保留字,下表中列出了标准 C语言中所定义的保留字。


autodoubleintstruct
breakelselongswitch
caseenumregistertypedef
charexternreturnunion
constfloatshortunsigned
continueforsignedvoid
defaultgotosizeofvolatile
doifstaticwhile

除了保留字之外,C语言中还有许多字符串与保留字类似,比如 printf 和 scanf 是 C语言标准函数库中的函数名称,我们也不能用它来做变量的名字。


像这些在 C语言标准函数库中已经定义并使用过的字符串我们称为 C语言的标准标识符。


除了标准标识符外,C语言允许用户自定义一些名称,比如给变量命名或者给用户自定义的函数命名等,这些由用户自定义的名称我们称为用户标识符。


最常见的用户标识符就是变量名。


下面这些都是不合法的变量名:

  • 86Count(不合法原因:以数字开头)
  • my name(不合法原因:包含空格)
  • user's(不合法原因:包含特殊字符‘)
  • int(不合法原因:C语言保留字)

另外,C语言中是严格区分大写字母与小写字母的。


比如 do 是保留字,而 Do、DO、dO 就不是,因而它们三个可以用作变量名。


通常情况下,C语言中的所有保留字、标准库函数名和普通标识符都只用小写字母表示,而常量名则通常用大写字母表示。


变量的分类

C语言中的变量分为局部变量和全局变量。



局部变量又称内部变量,由某对象或某个函数所创建的变量通常都是局部变量,只能被内部引用,而无法被其它对象或函数引用。



全局变量即外部变量,创建在函数的外部的变量,可以创建在程序中的任何位置。


全部变量是可以被本程序中的任何函数或对象调用的。


若一个局部变量被其他对象调用,会是一个空值,而全局变量则不会出现这中情况。


#include 
int global = 2022;//全局变量
int main()
{
    int local = 2020;//局部变量
    //下面定义的global会不会有问题?
    int global = 2021;//局部变量
    printf("global = %d\n", global);
    return 0; }
  • 上面的局部变量global变量的定义其实没有什么问题的!
  • 当全局变变量和局部变量重名时起作用的将是局部变量。


变量的作用域和生命周期

要创建大规模的C语言程序,必须首先理解程序中变量的作用域和生命周期。


作用域

变量的作用域是指一个变量在程序中起作用的区域,一般可以理解为变量所在的{ }的包围区域。


在程序块(一个{ }内)中声明的变量(一般称为局部变量),只在该程序块{ }中起作用。


也就是说,一个变量从被声明的位置开始,到包含该变量声明的程序块最后的大括号为止,这一区间内是起作用的。


这样的作用域称为块作用域。


而在 C 程序的 main( ) 函数以及其他自定义函数外面的程序开始部分声明的变量(一般称为全局变量),从声明位置开始,到该程序的结尾都是起作用的。


这样的作用域称为文件作用域。


  • 局部变量的作用域是变量所在的局部范围。


  • 全局变量的作用域是整个工程。


生命周期

变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。


  • 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。


  • 全局变量的生命周期是:整个程序的生命周期。


常量

C语言中的常量和变量的定义的形式有所差异。



C语言中的常量分为以下以下几种:

  • 字面常量
  • const 修饰的常变量
  • #define 定义的标识符常量
  • 枚举常量
#include 
//举例
enum Sex
{
 MALE,
 FEMALE,
 SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main()
{
    //字面常量演示
    3.14;//字面常量
    1000;//字面常量
    
    //const 修饰的常变量
    const float pai = 3.14f;   //这里的pai是const修饰的常变量
    pai = 5.14;//是不能直接修改的!
    
    //#define的标识符常量 演示
	#define MAX 100
    printf("max = %d\n", MAX);
    
    //枚举常量演示
    printf("%d\n", MALE);
    printf("%d\n", FEMALE);
    printf("%d\n", SECRET);
    //注:枚举常量的默认是从0开始,依次向下递增1的
    return 0; 
}
  • 上面例子上的 pai 被称为 const 修饰的常变量, const 修饰的常变量在C语言中只是在语法层面限制了
  • 变量 pai 不能直接被改变,但是 pai 本质上还是一个变量的,所以叫常变量。


C语言输入输出

C语言的输入和输出是用户和计算机之间的交互方式,其中有两个函数最常用,分别是 scanf() 和 printf():

  • scanf() 是格式输入函数,按用户指定的格式从键盘上把数据输入到指定变量中;
  • printf() 是格式化输出函数,主要功能是向标准输出设备按规定格式输出信息。


printf()和puts()的简单使用

程序在计算机的内存中运行,得出结果以后总是需要输出,这样我们才能查看程序的运行状况。


C语言用于输出的主要方法是使用格式输出函数 printf( ) 和字符串输出函数 puts( )。



printf( ) 函数的作用就是把字符、数字和单词发送到电脑屏幕上(屏幕打印)。



printf( )的一般格式如下:

printf("格式控制字符串",输出表列)//输出表列各项用符号,分隔开

puts( )函数是把字符串输出到电脑屏幕上并换行。


puts("Hello World!");                    //屏幕打印字符串消息并换行

只要把需要在屏幕上显示的字符串消息放在双引号中,电脑执行 printf( ) 和 puts( ) 语句时,就会在屏幕上原样打印出该字符串消息。


因为数字、字符在计算机内部都是以二进制数来存储和处理的,所以需要屏幕打印数字和字符时,必须准确地告诉 C 程序需要打印的内容是什么数据类型(格式)。


C语言使用转化字符来表明数据的格式。


下表列举了 C语言中常用的 4 种转化字符。


转化字符描述输出示例说明
%d整数printf("%d",16);输出整数 16
%f浮点数printf("%f",3.14);输出小数 3.140000
%c字符printf("%c",‘x’);输出字符 ‘x’
%s字符串printf("%s",“China”);输出字符串 “China”

如果仅仅输出一个字符串,则可以省略转化字符 %s,比如:

printf("%s","Hello World!");
可简写为:
printf("Hello World!");

但如果输出与其他数据组合的字符串时,必须用转化字符 %s,比如:

printf("%s 一斤 %f 元,%s 一斤 %d 元","苹果",2.5,"西瓜"2);


转化字符 %f 默认输出一个 6 位小数位的浮点数,如果不足 6 位,也会在后面补 0,如果超过 6 位则会四舍五入转化为 6 位小数位再输出。


使用 %.nf 的形式可以用其中的 n 来指定输出的小数位数,比如 %.2f 表示输出 2 位小数位的浮点数(见下图)。


printf()输出格式大全

%d、%f、%c 和 %s 只是 printf( ) 的格式控制字符串中转化字符的最简形式,printf() 格式控制字符串的完整形式为:

%[标志][输出最小宽度][.精度][数据长度]数据类型字符

其中,[ ]表示可选项。


  1. 数据类型字符
    用于表示输出数据的类型,其格式字符和意义如下表所示。


格式字符输出示例意义
dprintf("%d",16);以十进制输出带符号整数(正数不输出符号)
uprintf("%u",16);以十进制输出无符号整数
oprintf("%o",75);以八进制输出无符号整数(不输出前缀 0)
xprintf("%x",5B);以十六进制输出无符号整数(不输出前缀 0x)
fprintf("%f",3.14);以小数形式输出单、双精度实数
eprintf("%e",30000);以指数形式输出单、双精度实数
gprintf("%e",30000);以 %f、%e 中较短的宽度输出单、双精度实数
cprintf("%c",‘x’);输出单个字符
sprintf("%s",“Chi”);输出字符串
  1. 标志
    标志字符有 -、+、#、空格、0 五种,其意义如下表所示。


格式字符意义
-输出结果左对齐,右边填空格(和输出最小宽度搭配使用)
+输出结果右对齐,左边填空格(和输出最小宽度搭配使用),同时显示符号
#对 c、s、d、u 类无影响,对 o 类输出时加前缀 0,x 类输出时加前缀 0x
空格输出符号,值为正时冠以空格,为负时冠以负号
0放置在十进制整数的输出最小宽度前,用于当实际位数少于最小宽度时在前面补 0
  1. 输出最小宽度
    用十进制整数表示输出的最少位数,若实际位数多于定义的宽度,则按实际位数输出,实际位数少于定义的宽度则补以空格或 0。


  2. 精度
    精度格式符以小数点.开头,后跟十进制整数。


    如果输出数字,则表示其小数位数,如果输出字符,则表示输出字符的个数。


    若实际位数大于定义的精度,则截去超出的部分。


  3. 数据长度
    长度格式符有 h 和 l 两种。


    h 表示以短整型输出整数或以单精度输出浮点数,l 表示以长整型输出整数或以双精度输出浮点数。


scanf()函数用法

printf( ) 函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息,即把数据发送到屏幕。



而 scanf( ) 函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息并存储在变量中。



程序在运行过程中,必须得有一种方法从程序外部获得数据,并存储在某个变量中,不能总是使用赋值语句进行赋值。


例如,你编写一个 C 程序用于管理全班学生的考试成绩,你就不能在程序中用=把所有同学的成绩都赋值给变量,因为每次考试成绩都会不同,而且不同的班级考试成绩也不相同。


你需要在程序运行开始阶段提供一个功能,用于实时输入学生的考试成绩。


使用 scanf( ) 就可以实现这个功能。


scanf("格式控制字符串",变量地址表列)//变量地址编列各项用逗号隔开

如果掌握了用 printf( ) 把变量的值发送到屏幕,那么 scanf( ) 就很简单了。


scanf( ) 的书写格式看起来和 printf( ) 很像,他们都用到了转化字符如 %d 和 %s 等,例如:

printf("%d %f %c %s",Int,Float,Char,String);      //向屏幕输出值
scanf("%d %f %c %s",&Int,&Float,&Char,String);    //从键盘获取值

两者的不同之处在于 scanf( ) 中所有变量名前面必须加上&符号(字符串数组名前面不用加),尽管&符号并不是变量名的一部分。


只有变量前面加了&符号,scanf( ) 才能把从键盘获取到的数据正确存储到对应的变量中。


实际上,&符号在 C语言中是取址符,&Int 就是变量 Int 在内存中的地址。


scanf( ) 就是根据变量在内存中的地址把从键盘获取到的数据存储在变量中的,就如同快递员根据收件人的地址把包裹准确的投送到收件人手上一样。


而字符串数组是由多个数组元素变量组成的,数组名本身就对应于一个内存地址,所以 scanf( ) 中的字符串数组名前面不用加&符号。


scanf( ) 和 printf( ) 一样,在使用它们的 C 程序中,必须在程序的预处理指令部分添加指令包含 stdio.h 头文件:#include

scanf( ) 格式控制字符串中转化字符的一般形式为:

%[数据宽度][数据长度]数据类型字符      //[ ]为可选项 
  1. 数据类型字符:用于表示输入数据的类型,下表列出了其格式字符和意义。


格式字符输出示例意义
dscanf("%d",&Int);输入十进制整数
uscanf("%u",&Int);输入无符号十进制整数
oscanf("%o",&Int0);输入八进制整数
xscanf("%x",&Int0x);输入十六进制整数
fscanf("%f",&Float);输入小数形式的实数
escanf("%e",&Float);输入指数形式的实数
cscanf("%c",&Char);输入单个字符
sscanf("%s",String);输入字符串
  1. 数据宽度:用十进制整数指定输入数据的宽度(即字符数),若输入字符数超出指定值,超出部分被截去。


    例如:scanf("%5f",&Pi); 输入3.1415925,scanf( ) 只是把 3.141 这 5 个字符存储在了变量中,其余部分被截去。


    即用printf("%f",Pi);显示变量 Pi 的值为3.141000。


  2. 数据长度:长度格式符有 l 和 h 两种。


    l 表示输入长整型数(如 %ld )或双精度浮点数(如 %lf )。


    h 表示输入短整型数或单精度浮点数。


  • C 程序中通常要在scanf( )语句前面添加printf( )语句,用于在屏幕上输出提示信息,提示用户输入什么样的数据值。


使用scanf( )函数必须注意以下几点:

  1. scanf( )函数没有精度控制。


    如:

scanf("%.2f",&Pi);

是非法的格式控制字符串,不能企图用此语句输入小数位数为 2 的实数。


  1. scanf( ) 函数要求给出所有变量的地址,即变量名前加&符号(字符串数组名前不用加)。


    如:

scanf("%d %f %c %s",&Int,&Pi,&Char,String);

输入89 3.14 X China,回车后这 4 个数据会分别被存储进变量 Int、Pi、Char 和数组 String 中。



在用键盘输入多个数值时,若格式控制字符串中没有指定分隔符,则可用空格、Tab 键或回车键来做间隔,全部输入后用回车结束。


  1. 在输入字符数据时,若格式控制字符串中没有指定分隔符,则所有输入的字符均为有效字符(包括空格)。


    如:

scanf("%c%c%c%c%c",&a&b&c&d&e);

输入Mr smith,scanf( ) 会把 M 存储在变量 a 中,r 存储在变量 b 中,空格存储在变量 c 中,s 存储在变量 d 中,m 存储在变量 e 中,剩余部分被截去。


  1. 在输入字符串时,如果输入空格,则认为输入已结束。


    如:

scanf("%s",myName);

输入John Smith,scanf( ) 只把 John 存储在字符数组 myName 中,空格后的 Smith 被截去。


scanf( ) 函数输入格式化数据的实例如下面代码所示。


#include 
#include 
int main()
{
	char Char_A,Char_B;
	printf("请输入两个字符,然后回车:\n");
	scanf("%c%c",&Char_A,&Char_B);
	printf("\n使用scanf()获取输入值以后:\n");
	printf("变量Char_A的值为:%c\n",Char_A);   
	printf("变量Char_B的值为:%c\n",Char_B);
	system("pause");
	return 0;
}
  • 转化字符之间没有空格,输入的所有字符都将是有效字符,包括空格。



    运行结果:

请输入两个字符,然后回车:
M N

使用scanf()获取输入值以后:
变量Char_A的值为:M 变量Char_B的值为:
  • scanf( ) 的格式控制字符串中多个转化字符之间最好用空格分隔。


  • scanf( ) 函数与 printf( ) 函数配合使用的实例如下面代码所示。


#include 
#include 
int main()
{
	int age;
	float weight;
	char Name[15];
	printf("请输入您的姓名:");
	scanf("%s",Name);
	printf("请输入您的年龄:");
	scanf("%d",&age);
	printf("请输入您的体重(公斤):");
	scanf("%f",&weight);
	printf("\n以下是您输入的个人信息:\n");
	printf("姓名:%s\n",Name);
	printf("年龄:%d\n",age);
	printf("体重:%.2f公斤\n",weight);
	system("pause");
	return 0;
}
  • 程序运行到scanf( )后,暂停运行,等待用户输入数据;用户输入数据后继续运行下面的语句。



    运行结果:

请输入您的姓名:Magic
请输入您的年龄:22
输入您的体重(公斤):50

以下是您输入的个人信息:
姓名:Magic
年龄:22
体重:50.00公斤
字符串+转义字符+注释 字符串
"hello world.\n"

这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。


  • 注:字符串的结束标志是一个 \0 的转义字符。


    在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。


转义字符

假如我们要在屏幕上打印一个目录: c:\code\test.c
我们该如何写代码?

#include 
int main()
{
	printf("c:\code\test.c\n");
    return 0; 
}

实际上程序运行的结果是这样的:

这里就不得不提一下转义字符了。


转义字符顾名思义就是转变意思。



下面看一些转义字符。


转义字符释义
\?在书写连续多个问号时使用,防止他们被解析成三字母词
\’用于表示字符常量’
\“用于表示一个字符串内部的双引号
\用于表示一个反斜杠,防止它被解释为一个转义序列符。


\a警告字符,蜂鸣
\b退格符
\f进纸符
\n换行
\r回车
\t水平制表符
\v垂直制表符
\dddddd表示1~3个八进制的数字。


如: \130 X

\xdddd表示2个十六进制数字。


如: \x30 0

注释
  • 代码中有不需要的代码可以直接删除,也可以注释掉
  • 代码中有些代码比较难懂,可以加一下注释文字
    比如:
#include 
int Add(int x, int y) 
{
    return x+y; 
}
/*C语言风格注释
int Sub(int x, int y)
{
    return x-y;
}
*/
int main()
{
    //C++注释风格
    //int a = 10;
    //调用Add函数,完成加法
    printf("%d\n", Add(1, 2));
    return 0; 
}

注释有两种风格:

  • C语言风格的注释 /*xxxxxx */
    缺陷:不能嵌套注释
  • C++风格的注释 //xxxxxxxx
    可以注释一行也可以注释多行
C语言程序设计结构

包括C语言在内的几乎任何编程语言都支持以下三种程序设计结构,这三种流程结构如同小河中水流的三种形态,它们分别是:

  • 顺序结构程序设计(小河水毫无阻碍地向前流淌)
  • 选择结构程序设计(河水遇到分水岭分成几条支流)
  • 循环结构程序设计(河水在漩涡中不停打转)
顺序结构

顺序结构程序设计一般由三部分组成:

  • 输入部分:把已知的值输入电脑并存储在变量中。


  • 处理部分:按解决问题的次序进行计算处理。


  • 输出部分:把计算处理结果返回给用户。


下图展示了顺序结构程序设计的流程。


选择结构

选择结构的程序设计是一种根据判断条件的成立与否来确定下一步所做 *** 作的一种程序控制结构。


其程序的执行流程不再像顺序结构那样,从上到下一条条依次执行所有语句,而是根据判断条件的成立与否而走向不同的分支,因而,选择结构也被称为分支结构,如下图所示。




示例

#include 
int main()
{
    int coding = 0;
    printf("你会一直坚持下去吗?(选择1 or 0):");
    scanf("%d", &coding);
    if(coding == 1)
   {
       printf("坚持,你一定会成功\n");
   }
    else
   {
       printf("放弃,回家去种田\n");
   }
    return 0; }
循环结构

在日常工作和学习当中,我们经常会遇到一些大量而枯燥的重复性 *** 作,比如期末考试结束后计算每一位同学的总成绩和平均成绩,计算 1+2+3+…+1000 的和。


这些工作任何人去做都会感到厌烦而且也容易出错,而计算机可以使用循环(loop)控制轻松完成这些重复性 *** 作。


这些重复性的 *** 作不管重复多少次,最后总有结束的时候。


因而计算机的循环 *** 作也不是无限循环。


在编程时通常都要设置一个判断条件,当这个条件成立时,就重复 *** 作(循环),当条件不成立时,就结束这个重复 *** 作(循环)。


C语言中的循环控制结构有 3 种基本形式:

  • while 循环语句:当条件成立时,重复 *** 作,否则退出循环
  • do-while 循环语句:重复 *** 作,直到条件不成立时退出循环
  • for 循环语句:用循环变量准确控制重复 *** 作的次数

下图展示了循环控制结构的流程。



函数

函数可以理解为能够执行特定功能的“魔法盒”,使得多个处理步骤集中在一起并可以重复使用。


我们在编写 C语言程序时,可以根据实际需要自定义函数。


C语言程序的主体部分就是一个 main() 函数,每一个 C语言程序都是从 main() 函数开始执行的。


函数的特点就是简化代码,实现代码复用。


数组

要存储1-10的数字,怎么存储?
C语言中给了数组的定义:一组相同类型元素的集合

数组定义
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素
数组下标

C语言规定:数组的每个元素都有一个下标,下标是从0开始的。



数组可以通过下标来访问的。



比如:

int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9

数组使用
#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; 
}
*** 作符

算术 *** 作符

+ - * / %

移位 *** 作符

>> <<

位 *** 作符

& ^ |

赋值 *** 作符

=  +=  -=  *=  /=  &=  ^=  |=  >>=  <<=

单目 *** 作符

!           逻辑反 *** 作
-           负值
+           正值
&           取地址
sizeof       *** 作数的类型长度(以字节为单位)
~           对一个数的二进制按位取反
--          前置、后置--
++          前置、后置++
*           间接访问 *** 作符(解引用 *** 作符) (类型)       强制类型转换

关系 *** 作符

>
>=
<
<=
!=      用于测试“不相等”
==      用于测试“相等”

逻辑 *** 作符

&&      逻辑与
||      逻辑或

条件 *** 作符

exp1 ? exp2 : exp3

逗号表达式

exp1, exp2, exp3, …expN

下标引用、函数调用和结构成员

[] () . ->
常见关键字
auto   break  case   char    const  continue  default  do  double else  enum   
extern float  for    goto    if   int   long  register   return   short  signed
sizeof  static  struct  switch  typedef union  unsigned   void  volatile  while
关键字 typedef

typedef 顾名思义是类型定义,这里应该理解为类型重命名。



比如:

//将unsigned int 重命名为uint_32, 所以uint_32也是一个类型名
typedef unsigned int uint_32;
int main()
{
    //观察num1和num2,这两个变量的类型是一样的
    unsigned int num1 = 0;
    uint_32 num2 = 0;
    return 0; 
}
关键字static

在C语言中:
static是用来修饰变量和函数的

  1. 修饰局部变量-称为静态局部变量
  2. 修饰全局变量-称为静态全局变量
  3. 修饰函数-称为静态函数
修饰局部变量
//代码1
#include 
void test()
{
    int i = 0;
    i++;
    printf("%d ", i);
}
int main()
{
 int i = 0;
    for(i=0; i<10; i++)
   {
        test();
   }
    return 0; 
}
//代码2
#include 
void test()
{
    //static修饰局部变量
    static int i = 0;
    i++;
    printf("%d ", i);
}
int main()
{
	int i = 0;
    for(i=0; i<10; i++)
   {
        test();
   }
    return 0; 
}

对比代码1和代码2的效果理解static修饰局部变量的意义。


结论:

  • static修饰局部变量改变了变量的生命周期
  • 让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束
修饰全局变量
//代码1
//add.c
int g_val = 2022;
//test.c
int main()
{
    printf("%d\n", g_val);
    return 0; 
}
//代码2
//add.c
static int g_val = 2022;
//test.c
int main()
{
    printf("%d\n", g_val);
    return 0; 
}

代码1正常,代码2在编译的时候会出现连接性错误。


结论:

  • 一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。


修饰函数
//代码1
//add.c
int Add(int x, int y) 
{
    return c+y; 
}
//test.c
int main()
{
    printf("%d\n", Add(2, 3));
    return 0;
}
//代码2
//add.c
static int Add(int x, int y) 
{
    return c+y; 
}
//test.c
int main()
{
    printf("%d\n", Add(2, 3));
    return 0; 
}

代码1正常,代码2在编译的时候会出现连接性错误。


结论:

  • 一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。


#define 定义常量和宏
//define定义标识符常量
#define MAX 1000
//define定义宏
#define ADD(x, y) ((x)+(y))
#include 
int main()
{
    int sum = ADD(2, 3);
    printf("sum = %d\n", sum);
    
    sum = 10*ADD(2, 3);
    printf("sum = %d\n", sum);
    
    return 0; 
}
指针 内存

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。



所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。



为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。




变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。



取出变量地址如下:

#include 
int main()
{
	int num = 10;
	&num;//取出num的地址
	//注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)
	printf("%p\n", &num);//打印地址,%p是以地址的形式打印
	return 0; 
}


那地址如何存储,需要定义指针变量。


int num = 10;
int *p;//p为一个整形指针变量
p = &num;

指针的使用实例:

#include 
int main()
{
	int num = 10;
	int *p = &num;
	*p = 20;
	return 0; 
}


以整形指针举例,可以推广到其他类型,如:

#include 
int main()
{
	char ch = 'w';
	char* pc = &ch;
	*pc = 'q';
	printf("%c\n", ch);
	return 0; 
}
指针变量的大小
#include 
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
    printf("%d\n", sizeof(char *));
    printf("%d\n", sizeof(short *));
    printf("%d\n", sizeof(int *));
    printf("%d\n", sizeof(double *));
    return 0; 
}

结论:指针大小在32位平台是4个字节,64位平台是8个字节。


结构体

C语言结构体(Struct)可以理解为用户自定义的特殊的复合的“数据类型”,是多种类型的数据的集合体。


结构体类似于用于制作统一样式名片的空白模板,包含多种类型的数据。



结构体使得C语言有能力描述复杂类型,比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。



这里只能使用结构体来描述了。



例如:

struct Stu
{
    char name[20];//名字
    int age;      //年龄
    char sex[5];  //性别
    char id[15]//学号
};

结构体的初始化:

//打印结构体信息
struct Stu s = {"张三"20"男""20180101"};
//.为结构成员访问 *** 作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
//-> *** 作符
struct Stu *ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps- >id);

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/562244.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-01
下一篇 2022-04-01

发表评论

登录后才能评论

评论列表(0条)

保存