C语言基础(适合小白超级详细)

一、学习C语言前需要了解的常识

1.什么是计算机?

        计算机(computer)俗称电脑,是一种可以进行数值运算又可以进行逻辑运算的高速计算的电子计算机器。目前公认世界上第一台电子计算机是1946年在美国宾夕法尼亚大学诞生的ENIAC(Electronic Numerical Integrator And Calculator)。

2.计算机的组成

        计算机由硬件系统和软件系统组成。

        硬件系统主要由五部分构成:运算器、控制器、存储器、I/O设备(输入设备和输出设备)。CPU(Central Processing Unit),又称中央处理器,主要由运算器,控制器,寄存器构成。CPU是计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。现代计算机中CPU均采用冯诺依曼体系结构,在该体系结构下,程序和数据统一存储,指令和数据需要从同一存储空间存取,经由同一总线传输,无法重叠执行。

        软件系统主要分为系统软件和应用软件。系统软件一般包括操作系统、语言处理程序、数据库系统和网络管理系统。应用软件一般分为两类,一类是为特定需要开发的实用型软件,另一类是为了方便用户使用计算机而提供的一种工具软件。

3.什么是计算机程序?

        计算机程序是一组计算机能识别和执行的指令集。通俗的来讲就是人们通过计算机语言告诉计算机想要它做什么事,解决什么问题,如何工作等,每做一件事就是一条指令,而一条或多条指令的集合我们就称之为一个计算机程序。

指令:可以被计算机理解并执行的基本操作指令。

程序:一组计算机能识别和执行的指令。一个特定的指令序列用来完成一定的功能。

软件:与计算机系统操作有关的计算机程序、规程、规划,以及可能有的文件、文档及数据。

4.什么是计算机语言?

        计算机语言是一种人工设计的语言,用于人与计算机之间的信息交流。计算机语言主要分为机器语言、汇编语言和高级语言。

        机器语言:计算机能直接识别和接受的二进制代码称为机器指令。机器指令的集合就是该计算机的机器语言

        特点:难学,难记,难检查,难修改,难以推广使用。依赖具体机器难以移植。

B8  7F 01

BB  21 02

03   D8

B8  1F 04

2B  C3

        汇编语言:机器语言的符号化。用英文字母和数字表示指令的符号语言

        特点:相比机器语言简单好记,但仍然难以普及。汇编指令需通过汇编程序转换为机器指令才能被计算机执行。依赖具体机器难以移植。

MOV  AX  383

MOV  BX  545

ADD   BX  AX

MOV  AX  1055

SUB    AX  BX

        高级语言:更接近于人们习惯使用的自然语言和数学语言。

        特点:功能强大,不依赖于具体机器。用高级语言编写的源程序需要通过编译程序转换为机器指令的目标程序

S=1055-(383+545)

        高级语言的发展,由最原先的非结构化,再到结构化,再到目前面向对象的语言。在发展到结构化语言时就已规定程序必须由具有良好特性的基本结构(顺序结构、选择结构、循环结构)构成,程序中的流程不允许随意跳转,程序总是由上而下顺序执行各个基本结构。这样编写出来的程序结构清晰,易于编写、阅读和维护。

5.什么是C语言?

        C语言是一门通用计算机高级语言,被广泛应用于底层开发,是1972-1973年间由D.M.Ritchie在B语言的基础上设计出了C语言。最初的C语言只是为了描述和实现UNIX操作系统提供一种工作语言而设计的。随着UNIX的日益广泛使用,C语言也迅速得到推广。1978年以后,C语言先后移植到大、中、小和微型计算机上。C语言便很快风靡全世界,成为世界上应用最广泛的程序设计高级语言。

        C语言具有以下特点:

        1.语言简洁、紧凑、使用方便、灵活。

        2.运算符丰富。

        3.数据类型丰富。

        4.有结构化的控制语句(用函数作为程序的模块单位,便于实现程序的模块化,而C语言是完全模块化和结构化的语言)。

        5.语法限制不太严格,程序设计自由度大。

        6.允许直接访问物理地址,能进行位(bit)操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作(因此C语言既具有高级语言的功能,又具有低级语言的许多功能,可用来编写系统软件)。

        7.程序可移植性好。

        8.生成目标代码质量高,程序执行效率高。

二、C语言程序

1.如何新建一个C语言项目

        还未撰写。

2.如何创建一个C语言文件

        还未撰写。

3.C语言程序的构成

C 程序主要包括以下部分:

  • 预处理指令
  • 函数
  • 变量
  • 语句&表达式
  • 注释

        下面来看最简单的C语言程序

要求:在屏幕上输出:This is a C program.

#include <stdio.h>                          //这是编译器预处理指令
int main()                                  //定义主函数
{                                           //函数开始的标志
    printf("This is a C program.\n");       //输出所指定的一行信息
    return 0;                               //函数执行完毕时返回函数值0
}                                           //函数结束的标志

运行结果

程序分析:

        在使用函数库中的输入输出函数时,编译系统要求程序提供有关此函数的信息,程序第1行“#include <stdio.h>”的作用就是用来提供这些信息的。stdio.h是系统提供的一个文件名,stdio是standard input & output的缩写,文件后缀.h的意思是头文件(header file),因为这些文件都是放在程序各文件模块的开头的。输入输出函数的相关信息已事先放在stdio.h文件中。

        main是函数的名字,表示“主函数”。每一个C语言程序都必须有一个main函数。main前面的int表示此函数的类型是int类型(整形),即在执行主函数后会得到一个值(即函数值),其值为整形。return 0;的作用是当main函数执行结束前将整数0作为函数值,返回到函数调用处。而函数体由花括号{}括起来。

        printf是C编译系统提供的函数库中的输出函数。printf函数中双引号内的字符串″This is a C program.″按原样输出。\n是换行符,即在输出″This is a C program.″后,显示屏上的光标位置移到下一行的开头。 每个语句最后都有一个分号,表示语句结束。

        //表示从此处到本行结束是“注释”,用来对程序有关部分进行必要的说明。在写C程序时应当多用注释,以方便自己和别人理解程序各部分的作用。在程序进行预编译处理时将每个注释替换为一个空格,因此在编译时注释部分不产生目标代码,注释对运行不起作用。注释只是给人看的,而不是让计算机执行的。

4.注释

        由上一个程序可以看出,程序在编译运行时,代码中所有注释的内容都会被编译器跳过,不会被编译器执行。那什么是注释呢?注释是在所有计算机语言中都非常重要的一个部分,通俗来讲就是注解、解释的意思,注释可以是任何符号文字,它可以被用在某一段或者某一行代码用来解释其含义,方便程序后期的维护,提高程序的可读性。因此,一个程序员必须要具备勤写注释的良好习惯。

        注释一共分为两种,单行注释(//  )和多行注释(/*  */)。

        以//开始的是单行注释。这种注释可以单独占一行,也可以出现在一行中其他内容的右侧。此种注释的范围从//开始,以换行符结束。如果注释内容一行内写不下,可以用多个单行注释。

        以/*开始,以*/结束的块式注释是多行注释。这种注释可以包含多行内容。它可以单独占一行(在行开头以/*开始,行末以*/结束),也可以包含多行。编译系统在发现一个/*后,会开始找注释结束符*/,把二者间的内容作为注释。

注意:在字符串中的//和/*都不作为注释的开始。而是作为字符串的一部分。

#include <stdio.h>
int main()
{
	printf("//Hello World!//\n\n");
	printf("/*How are you?*/");
    return 0;
}

运行结果:

三、关键字和标识符

1.什么是关键字?

        C语言关键字(Keywords)是C语言编程语言中预先定义并保留的标识符,它们具有特定的含义,并用于构成C语言程序的基本结构和功能。在开发工具中,这些关键字会显示出与其他代码不一样的颜色。关键字不能用作变量名、函数名或其他标识符的名称。请注意,关键字是区分大小写的,并且通常以小写字母开头(除了_Bo01,它可以是Bo01或bo01)。在编写C语言程序时,应避免使用这些关键字作为标识符的名称。

2.关键字的分类(32个)

数字类型关键字:用于声明变量的数据类型。

类型关键字用途
基本数据类型关键字char定义字符型类型变量
int定义整型类型变量
float定义浮点型类型变量(单精度)
double定义浮点型类型变量(双精度)
类型修饰关键字short修饰int,声明短整型类型数据,可省略被修饰的int
long修饰int,声明长整型类型数据,可以省略被修饰的int
signed修饰整形类型数据,声明有符号数据类型
unsigned修饰整形类型数据,声明无符号数据类型
复杂类型关键字struct结构声明体
union共用声明体
enmu枚举声明

控制语句关键字:用于控制程序的流程。

类型关键字用途


 

分支结构


 

ifif条件语句
else条件语句否定分支(与if配合使用)
switch开关语句(与case、default配合使用)
case开关语句中的分支标记
default开关语句中的“其他”分支

循环结构

 

forfor循环语句
whilewhile循环语句
dodo……while循环语句

跳转结构

 

continue跳过语句(配合循环结构使用)
break跳出语句(配合循环结构以及switch使用)
goto(不常用)无条件跳转语句
return返回语句,用于返回特定值

存储类型关键字:用于定义变量的存储类别。

关键字用途
auto指定为自动变量
register指定为寄存器变量
static指定为静态变量
extern指定对应变量为外部变量
const指定变量为只读变量
volatile指定变量为易变变量

特殊用途关键字:具有特殊用途的关键字。

关键字用途
void空类型(不能定义变量,修饰函数的参数或返回值,表示没有)
sizeof计算数据类型长度
typedef声明类型别名

3.标识符

        C语言中的标识符(ldentifier)是用于命名变量、函数、类型、标签和其他用户定义项的名称。通俗的来讲就是方便程序员区分程序中的众多函数,给这些不同的函数起了不同的名称,这些名称就是标识符。这些标识符在C语言中是由程序员自行选择的,但必须遵循一些基本规则,以便编译器能够正确解析它们。

标识符的命名规则:

        一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。C 标识符内不允许出现标点字符,比如 @、$ 和 %。C 是区分大小写的编程语言。因此,在 C 中,Manpowermanpower 是两个不同的标识符。C语言的标识符命名规则可以总结为以下几点。

1.只能由数字、字母、下划线组成。

2.不能以数字开头。

3.不能使用C语言的关键字。

4.好的命名习惯要做到见名知义

 (1)大驼峰命名法:每个单词首字母大写。例如:MyFirstName

 (2)小驼峰命名法:从第二个单词开始,首字母大写。例如:myFirstName

 (3)下划线命名法:每个单词之间用_连接。例如:my_first_name

以下列出一些标识符:

_name(合法)、1name(不合法)、Adress(合法)、MyName(合法)、last-test(不合法)、first#test(不合法)、final_test(合法)

四、数值表示

        数据在计算机中是以二进制形式存储的。

1.进制

        进制也就是进位制,是人们规定的一种进位方法,也是一种计数的方式。常见的进制有二进制、八进制、十进制、十六进制。对于任何一种进制X进制,就表示某一位置上的数在运算时是逢X进一位。十进制是逢十进一,十六进制是逢十六进一,八进制是逢八进一,二进制是逢二进一。

十进制二进制八进制十六进制
0000
1111
21022
31133
410044
510155
611066
711177
81000108
91001119
10101012A
11101113B
12110014C
13110115D
14111016E
15111117F
161 00002010

2.二进制

        二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。

        十进制转化二进制的方法:用十进制数除以2,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果。

        二进制转化十进制的方法:从二进制的右边第一个数开始,每一个乘以2的n次方,n从0开始,每次递增1。然后得出来的每个数相加即是十进制数。八进制、十六进制转化十进制同理,只是乘以的是8的n次方、16的n次方。

        从上述运算可以总结出一个二进制转化十进制更快的方法,也是最常用的方法

3.八进制

        八进制,Octal,缩写OCT或O,一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1。一些编程语言中常常以数字0开始表明该数字是八进制。八进制的数和二进制数可以按位对应(八进制一位对应二进制三位),因此常应用在计算机语言中。

        十进制转化八进制的方法:用十进制数除以8,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果。

        八进制和二进制互转:八进制数的每一位对应二进制数的三位,八进制转化二进制即将八进制数的每一位分别转化为三位二进制数后,按序三位一空排列得到的就是对应的二进制数。同理,二进制转化八进制即将二进制数从右边第一位开始每三位转为对应的八进制数后,按序排列得到的数就是对应的八进制数。

4.十六进制

        十六进制(英文名称:Hexadecimal),同我们日常生活中的表示法不一样,它由0-9,A-F组成,字母不区分大小写。与十进制的对应关系是:0-9对应0-9,A-F(或a-f)对应10-15。十六进制的数和二进制数可以按位对应(十六进制一位对应二进制四位),因此常应用在计算机语言中。

        十六进制和二进制互转:十六进制数的每一位对应二进制数的四位,十六进制转化二进制即将十六进制数的每一位分别转化为四位二进制数后,按序四位一空排列得到的就是对应的二进制数。同理,二进制转化十六进制即将二进制数从右边第一位开始每四位转为对应的十六进制数后,按序排列得到的数就是对应的十六进制数。

二进制  1001 1001 →     八进制 (每三位一组) 0 231 →      十六进制 (每四位一组)0x99

C语言在表示响应的进制数时:

十进制:以正常数字1~9开头                     //45

二进制:以0b或0B开头                             //0b101101

八进制:以0开头                                       //055

十六进制:以0x或0X开头                          //ox88

5.数值的存储方式

        计算机底层存储数据都是采用二进制,但二进制也有几种类型:原码、反码、补码、移码。下面让我们了解他们的意义以及作用。

  • 原码

十进制数按照:除二取余、倒序排列,得到的就是原码。 

      10  ->  0000 1010
     -10  ->  1000 1010
      -1   ->  1000 0001
       1   ->  0000 0001

此时原码在做计算时会出现正负数的加法以及零的问题。

  ● 正负数加法:

     -1+1=0

     1000 0001

+   0000 0001

 ---------------------

     1000 0010       ->    -2   ?

  ● 正负零:

  十进制数中,+0和-0是一个数,但是0却占了两个二进制:0000 0000(+0)、1000 0000(-0)


  • 反码

为了解决上面的问题,出现了反码,反码的计算规则如下:

  ●正数的反码就是原码本身;

  ●负数的反码是按位取反(但符号位不变);

示例:

    1 -> 0000 0001 -> 0000 0001
   -1 -> 1000 0001 -> 1111  1110

     1111 1110

+  0000 0001

 ---------------------

     1111 1111     

        1111 1111 是运算完之后的结果,但要注意,这时还是反码,需要重新返回来:1000 0000 。
反码解决了正负数加法问题,但正负零的问题还是存在。


  • 补码

补码的计算规则如下:

  ●正数的补码就是原码本身;

  ●负数的补码就是在反码的基础上+1;

        1 -> 0000 0001 -> 0000 0001 -> 0000 0001
        -1 -> 1000 0001 -> 1111 1110 ->  1111  1111

    0000 0001

+  1111  1111

 ---------------------

    0000 0000     

正负0的问题也相应解决了:

  +0:0000 0000

   -0:1000 0000   -> 1111 1111(反码)  -> 0000 0000(补码)

        补码在正负数加减法运算时没问题,也不会出现正负零占两个二进制。但 1000 0000 不表示为负零,用来表示什么呢?计算机其实默认把8位有符号二进制 1000 0000 表示为 -128 。


  • 移码

        补码符号位取反就是移码,一般用来计算浮点数作为阶码和比较数的大小使用。

十进制数

补码

移码

+15

0000 1111

1000 1111

-15

1111 0001

0111 0001

+0

0000 0000

1000 0000

五、数据类型

        计算机中存储数据的形式分为静态数据和动态数据。静态数据是指一些永久性的数据,一般存储在硬盘中。计算机关闭之后再开启,这些数据仍会存在,除非主动删除或者硬盘损坏,这些数据一直都会存在。动态数据是指在程序的运行过程中,动态产生的临时数据,一般存储在内存中。计算机关闭之后,这些临时数据就会被清除。

1.字节和地址

        在了解C语言的数据类型之前,需要先了解什么是计算机的字节和地址。

  • 位(bit):简写为“b”,读作比特,是计算机中最小的数据单位,使用二进制,只能表示0和1。
  • 字节(Byte):又称字节单元或字节存储单元,是计算机信息中用于描述存储容量和传输容量的一种计量单位,是计算机技术中最小的可操作存储单位一个字节由8位组成,从0000 0000到1111 1111,表示0~255之间的数字,也可以表示单个字符。计算机访问内存的基本单位是字节。
名称简写换算
字节B1B=8b(bit)
千字节KB1KB=2^10B=1024B
兆字节MB1MB=2^10KB=1024KB
吉字节GB1GB=2^10MB=1024MB
太字节TB1TB=2^10GB=1024GB
拍字节PB1PB=2^10TB=1024TB
………………

  • 地址:为了有效地使用内存,将内存划分为一个个小的内存单元,每个内存单元的大小是一个字节。为了能够快速有效地访问每个内存单元,就给这些内存单元进行了编号,这些编号就叫做该内存单元的地址。
  • 地址编号:在32位平台下,内存单元的地址是由32位的二进制数(即8位十六进制数)依次编号。所以内存单元共有2^32个,而每一个内存单元保存1个字节的内容。

        C语言中定义变量,都是在程序运行起来后在内存中开辟空间。

2.C语言数据类型

        在 C 语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。通俗来说一个C程序在内存中运行过程中会产生各种各样的临时数据,为了方便数据的运算和操作,C语言对这些数据进行了分类,提供了丰富的数据类型。

        C语言的数据类型一共分为四大类:基本数据类型、枚举类型、空类型、派生类型。

类型描述
基本数据类型

它们是算术类型,包括整型(int)、字符型(char)、浮点型(float)和双精度浮点型(double)。

枚举类型

它们也是算术类型,被用来定义在程序中只能赋予其一定的离散整数值的变量。

空类型

也称为void类型。表示没有值的数据类型,通常用于函数返回值。

派生类型

包括数组类型、指针类型和结构体类型。

这里先介绍一下基本数据类型,它一共分为两种:数值类型和字符类型。其中数值类型又分为整型和浮点型。

类型存储大小值范围
字符类型char1字节-128~127或0~255




整形


 
unsigned char1字节0~255
signed char1字节-128~127
int2或4字节

-32,768~32,767 或

-2,147,483,648~2,147,483,647

unsigned int2或4字节

0~65,535 或

0~4,294,967,295

short2字节-32,768~32,767
unsigned short2字节0~65,535
long4字节-2,147,483,648~2,147,483,647
unsigned long4字节0~4,294,967,295

浮点型
 
float(单精度)4字节1.2E-38~3.4E+38
double(双精度)8字节2.3E-308~1.7E+308
long double(双精度)16字节3.4E-4932~1.1E+4932

void 类型指定没有可用的值。它通常用于以下三种情况下:

序号类型与描述
1

函数返回为空:
C 中有各种函数都不返回值,或者可以说它们返回空。不返回值的函数的返回类型为空。例如 void exit (int status);

2

函数参数为空
C 中有各种函数不接受任何参数。不带参数的函数可以接受一个 void。例如 int rand(void);

3

指针指向 void
类型为 void * 的指针代表对象的地址,而不是类型。例如,内存分配函数 void *malloc( size_t size ); 返回指向 void 的指针,可以转换为任何数据类型。

3.类型转换

        既然已经定义了数据类型,C语言为什么还要进行类型转换?那是因为计算机硬件在进行算术操作时,要求各操作数的类型具有相同的存储位数以及一样的存储方式,所以就出现了类型转换。

        C 语言中有两种类型转换:

  • 隐式类型转换:隐式类型转换是在表达式中自动发生的,无需进行任何明确的指令或函数调用。它通常是将一种较小的类型自动转换为较大的类型,例如,将int类型转换为long类型或float类型转换为double类型。隐式类型转换也可能会导致数据精度丢失或数据截断。

        char类型数据转换为int类型数据遵循ASCII码中的对应值。

注意: 1、字节小的可以向字节大的自动转换以保证精确度不降低,但字节大的不能向字节小的转换。

            2、char类型可以转换为int,int可以转换为double,char可以转换为double,但反过来不行。

#include<stdio.h>
int main()
{
	//自动类型转换  隐式类型转换 :编译器自动转换
	int a = 11;
	double b = a;                 //将a的值11,转换为11.0000,再给b赋值 
	printf("b = %lf\n", b);
	printf("a = %d\n", a);
	printf("%lf\n", 12 / 3);      //异常结果0.000000
	printf("%lf\n", 12 / 3.0);    // 其中一个必须是浮点数才可以
	return 0;
}

运行结果如下:

自动类型转换:字节小的向字节大的转——隐式:编译器自动完成

 (1)算术转换:进行算术运算时,不同类型的数据必须转换成同一数据类型才能运算。在进行运算时, 以表达式中最长类型为主,将其他数据类型均转换为该类型。

 (2)赋值转换: 赋值转换 //进行赋值操作时,赋值运算符右边的数据类型必须转换成赋值号左边的类型, 若右边的数据类型的长度大于左边,则要进行截断或舍入操作。

 (3)输出转换:在程序中,用printf以指定格式输出时,当要输出的数据类型与指定类型不符合时,会进行类型转换。

算术转换示例如下:

#include<stdio.h>
int main()
{
	int a = 10;
	double b = 3.14;
	printf("a+b=%lf\n", a + b);       //13.140000
	char ch = 'a';
	printf("a+12=%d\n", ch + 12);     //109
    return 0;
}

赋值转换示例如下:

#include <stdio.h>
int main()
{
    char c = 'b';
    int i, result;
    i = 2;
    double d = 1.5;
    float m = 1.20000;               //从“double”到“float”截断    1.20000f
    result = c / i + (d * m);        //分析result的类型  
                                     //c/i=98/2=49
                                     //1.5*1.2=1.8
                                     //49+1.8= 50(因为变量result被定位为整型) 
    printf("result = %d\n", result); //result=50 
}

输出转换示例如下:

#include <stdio.h>
int main()
{
int a = 9;
printf("%f\n", a);   //出错    0.000000

float b = 90.5f;
printf("%d\n", b);   //出错    0

long c = 90;
printf("%d\n", c);   //正常转换

char ch = 'a';
printf("%d\n", ch);  //正常
      
long d = 8000;       //较长类型往较短类型转换时,不能超出较短类型的范围   
printf("%d\n", d);   //正常    8000

return 0;
}
  • 显式类型转换:显式类型转换需要使用强制类型转换运算符(type casting operator),它可以将一个数据类型的值强制转换为另一种数据类型的值。强制类型转换可以使程序员在必要时对数据类型进行更精确的控制,但也可能会导致数据丢失或截断。
#include<stdio.h>
int main()
{
	double d = 3.14159;
	int i = (int)d; // 显式将double类型转换为int类型
	printf("i=%d", i);
	return 0;
}

运行结果如下:

在使用强制转换时应注意以下问题:

  • 数据类型和表达式都必须加括号, 如把(int)(x/2+y)写成(int)x/2+y则成了把x转换成int型之后再除2再与y相加了。
  • 转换后不会改变原数据的类型及变量值,只在本次运算中临时性转换。
  • 强制转换后的运算结果不遵循四舍五入原则。
#include<stdio.h>
int main()
{
//强制类型转换  语法:(类型)(变量)
        int a = 3;
        int b = 2;
        printf("%lf\n", (double)(a / b));   //1.000000  先转整再转double
        printf("%lf\n", (double)a / b);     //1.500000
        printf("%lf\n", (double)(10 / 3));  //3.00000000  出错
        printf("%lf\n", (double)10 / 3);    //3.333333

//ASCLL表中  字符最大是127(字符占一个字节,8位  最大值是127)
        int c = 100;
        char d = (char)c;
        printf("%d\n", d);                  //正常


        int e = 200;                        //如果取大于127的值就会出错,数据可能会丢失
        char f = (char)e;
        printf("%d\n", f);                  //数据丢失   -56

        return 0;
}

六、变量和常量

Ⅰ.变量

1.什么是变量?

        变量,从字面角度上来看就是可以变化的量。在生活中树的高度、人的身高、行驶中汽车的速度等,数值不固定的数据。在C语言中,变量可以通俗理解为哆啦A梦的口袋,可以将不同类型的东西装进去也可以拿出来用。严格意义上来说,变量代表一个有名字的、具有特定属性且用来存储和标记数据的容器,可以根据数据的类型和名称进行访问和修改。

2.变量的定义

        在C语言中,定义一个变量就是为这个变量分配存储空间,还可以为变量指定初始值。程序中,变量有且仅有一个定义。那么如何去定义一个变量呢?定义一个变量的语法格式如下:

变量类型  变量名称          int  a;                //定义一个变量名称为a的整型变量

                                         double  b;        //定义一个变量名称为b的浮点型变量

                                         char c,d,e;       //定义三个变量名称分别为c,d,e的字符型变量

        我们通常定义一个变量的目的是为了去使用这个变量,只有先定义了变量系统才会为其分配存储空间去存储数据。由第四章学习了什么是数据类型我们可以知道,在定义变量时首先要定义它所存储的数据是哪一种数据类型,也就是定义这个变量的变量类型,一旦定义了一个变量的变量类型,那么这个变量就只能存储这个类型的数据。其次要定义变量的变量名称,因为我们没法从偌大的存储空间取出我们想要的值,只有定义了变量名称系统才能根据变量名称从而找到存储空间中变量的地址,从而取出我们想要的值。变量名称的定义必须严格按照标识符的命名规则。

3.变量的赋值

        在定义好一个变量后我们就可以往这个变量里存储数据,也就是给变量赋值。首先看一下如何给一个变量赋值。

int  a;           //定义一个整形变量a

a=5;             //将5赋值给变量a

这里需要特别注意一点,a=5这条语句不是我们平常在数学运算中的a等于5,而是将右边的整型常量5赋值给左边的整型变量a。在赋值时,“=”的左边必须是变量,不能将这条语句写为10=b。

4.变量的初始化

        C语言中,变量的第一次定义我们称之为变量的初始化。定义一个变量时,如果不进行初始化,它会存储随机数、上次程序分配的存储空间,存数一些内容,“垃圾”或系统正在用的一些数据,也会使程序运行出不正确的结果。变量的初始化语法格式如下:

int  a;                     //先定义,后初始化

a=5;

int  b = 10;            //定时的同时初始化

int c,d=e=15;     //定义整型变量c,d,e的同时初始化变量d,e

5.如何对变量的值进行操作?

        当我们把一个值赋值给一个变量,如何去查看这个变量的值呢?我们使用printf函数输出一个或多个变量的值。

int a=5,b=10,c='A';

printf("a=%d,b=%d,c里面存储的字符是%c",a,b,c);        //a=5,b=10,c里面存储的字符是A

        当我们定义了一个变量并已经初始化它的值或已经赋过值,我们仍可以按照自己的需求对变量继续进行多次赋值,也可以将其他变量存储的值赋值给指定变量,每次赋值都会覆盖原来的值。

int a=5;           //定义并初始化整型变量a,此时变量a里存储的值为5

a=10;             //对a重新赋值,此时变量存储的值为10

int x=20;

int y=x;          //定义一个整型变量y,并将变量x中存储的值赋值给变量y

                     //此时变量x,y存储的值都为20

6.变量的作用域

        变量按作用域的范围可以分为两种:局部变量和全局变量。在C语言中,变量定义的位置不同,其作用域也不同。局部变量也成为内部变量,是在代码块内定义的,其作用域仅限于代码块内,离开该代码块后无法使用。全局变量也称为外部变量,它是在代码块外部定义的变量。同一作用域范围内不能有相同名称的变量,不同作用域范围内可以有相同名称的变量。

局部变量:                                                                        全局变量:                                   

int main(){                                                                          int a=5;

{                         //作用域开始                                            int main(){    

int a=5;                                                                              int b=10;

printf("%d",a);    //可以输出                                               printf("%d",a+b);   //可以输出,15

}                         //作用域结束                                            return 0;

printf("%d",a);    //无法输出                                                }

return 0;

}

        C 语言中变量的默认值取决于其类型和作用域。全局变量和静态变量的默认值为 0,字符型变量的默认值为 \0,指针变量的默认值为 NULL,而局部变量没有默认值,其初始值是未定义的。

Ⅱ.常量

1.什么是常量?

        常量,通俗的理解为固定不变的数据,值不能改变的量,例如一个人的生日、一月有31天、字母一共有26个等等。在C语言中常量是指在程序运行过程中其值不能被改变的量

2.常量的分类

        C语言中常量可分为直接整数常量、浮点常量、字符常量、字符串常量(还有枚举常量、自定义常量等等,这里只列举了经常用到的类型)

整型常量:

        整型常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。

        整型常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。

357        //十进制
0213       //八进制
0x4b       //十六进制
357         //整数
357u        //无符号整数
357l        //长整数
357ul       //无符号长整数

浮点常量:

        浮点常量由整数部分、小数点、小数部分和指数部分组成。可以使用小数形式或者指数形式来表示浮点常量。

        当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的,例如数学上的科学计数法1234000000表示为1.234×10⁹,在C语言中表示为1.234e9或1.234E9。

C语言表示科学计数法注意事项:

  • 字母e或字母E后面的指数必须为整数
  • 字母e或字母E前后必须要有数字
  • 字母e或字母E前后不能有空格

字符常量:

        字符常量是括在单引号中,例如,'x' 可以存储在 char 类型的简单变量中。它可以是一个普通的字符(例如 'x')、一个转义序列(例如 '\t'),或一个通用的字符(例如 '\u02C0')。

        在 C 中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。下表列出了一些这样的转义序列码:

转义序列含义
 \\\字符
\'‘字符
\''"字符
\??字符
\a警报铃声
\b退格键
\f换页符
\n换行符
\r回车
\t水平制表符
\v垂直制表符
\ooo一到三位的八进制数
\xhh……一个或多个数字的十六进制数

字符串常量:

        一个字符串包含类似于字符常量的字符:普通的字符、转义序列和通用的字符。通常出现在 "  "中,可以使用空格做分隔符,把一个很长的字符串常量进行分行。下面这三种形式所显示的字符串是相同的。

  • "hello,world"
  • "hello,/

        world"

  • "hello," "w" "orld"

        字符串常量在内存中以 null 终止符 \0 结尾。例如:

char SenTence[] = "Hello, world!";      //系统对字符串常量自动加一个 '\0'

3.如何定义常量

在 C 中,有两种简单的定义常量的方式:

        1.使用 #define 预处理器: #define 可以在程序中定义一个常量,它在编译时会被替换为其对应的值。

        2.使用 const 关键字:const 关键字用于声明一个只读变量,即该变量的值不能在程序运行时修改。

#define预处理器

下面是使用 #define 预处理器定义常量的形式:

        #define 常量名 常量值

下面的代码定义了一个名为 PI 的常量:

        #define PI 3.14159在程序中使用该常量时,编译器会将所有的 PI 替换为 3.14159。

#include <stdio.h>
 
#define LENGTH 10   
#define WIDTH  5
#define NEWLINE '\n'
 
int main()
{
 
   int area;  
  
   area = LENGTH * WIDTH;
   printf("value of area : %d", area);
   printf("%c", NEWLINE);
 
   return 0;
}

运行结果如下:

const关键字

可以使用 const 前缀声明指定类型的常量,const 声明常量要在一个语句内完成,通常把常量定义为大写字母形式。如下所示:

        const 数据类型 常量名 = 常量值;

例如:          const int VAR = 5;       

错误写法:   const int VAR;             ×

                     VAR=5;                       ×

下面的代码定义了一个名为MAX_VALUE的常量:

        const int MAX_VALUE = 100;在程序中使用该常量时,其值将始终为100,并且不能被修改。

#include <stdio.h>
 
int main()
{
   const int  LENGTH = 10;
   const int  WIDTH  = 5;
   const char NEWLINE = '\n';
   int area;  
   
   area = LENGTH * WIDTH;
   printf("value of area : %d", area);
   printf("%c", NEWLINE);
 
   return 0;
}

运行结果如下:

#define 与 const 区别

        #define 与 const 这两种方式都可以用来定义常量,选择哪种方式取决于具体的需求和编程习惯。通常情况下,建议使用 const 关键字来定义常量,因为它具有类型检查和作用域的优势,而 #define 仅进行简单的文本替换,可能会导致一些意外的问题。

#define 预处理指令和 const 关键字在定义常量时有一些区别:

  • 替换机制:#define 是进行简单的文本替换,而 const 是声明一个具有类型的常量。#define 定义的常量在编译时会被直接替换为其对应的值,而 const 定义的常量在程序运行时会分配内存,并且具有类型信息。
  • 类型检查:#define 不进行类型检查,因为它只是进行简单的文本替换。而 const 定义的常量具有类型信息,编译器可以对其进行类型检查。这可以帮助捕获一些潜在的类型错误。
  • 作用域:#define 定义的常量没有作用域限制,它在定义之后的整个代码中都有效。而 const 定义的常量具有块级作用域,只在其定义所在的作用域内有效。
  • 调试和符号表:使用 #define 定义的常量在符号表中不会有相应的条目,因为它只是进行文本替换。而使用 const 定义的常量会在符号表中有相应的条目,有助于调试和可读性。

指针

1.什么是指针?

        在介绍指针之前,必须先弄清楚数据在内存中是如何存储的,又是如何读取的。如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定的长度空间。内存区的每一个字节都有一个编号,这就是“地址”它相当于旅馆中的房间号。在地址所标志的内存单元中存放的数据则相当于旅馆房间中居住的旅客。

        由于通过地址能找到所需的变量单元,可以说地址指向该变量单元。打个比方,一个房间的门口挂了一个房间号2008,这个2008就是房间的地址,或者说,2008“指向”该房间。因此,将地址形象化地称为“指针”,通过它能找到以它为地址的内存单元。C语言中的地址包括位置信息(内存编号,或称纯地址)和它所指向的数据的类型信息,或者说它是“带类型的地址”。如&a,一般称它为“变量a的地址”,确切地说,它是“整型变量a的地址”,后续提到的“地址”,都是这个意思。

2.变量的访问方式

        在程序中一般是通过变量名来引用变量的值,对变量的访问都是通过地址进行的。

int a=10,c;

scanf("%d",&c);

printf("a=%d,c=%d",a,c);

        这种直接按变量名进行的访问,称为“直接访问”方式。还可以采用另一种称为“间接访问”的方式,即将变量a的地址存放在另一变量b中,然后通过变量b来找到变量a的地址,从而访问a变量。

int *b=&a;                    //将a的地址存放到指针变量b中

printf("a=%d",*b);        //通过变量a的地址从而找到a并取值

        打个比方,为了开一个A抽屉,有两种办法,一种是将A钥匙带在身上,需要时直接找出该钥匙打开抽屉,取出所需的东西。另一种办法是:为了安全起见,将该A钥匙放到另一抽屉B中锁起来。如果需要打开A抽屉,就需要先找出B钥匙,打开B抽屉,取出A钥匙,再打开A抽屉,取出A抽屉中之物,这就是“间接访问”。

3.指针变量

        有一个变量专门用来存放另一变量的地址(即指针),则它称为“指针变量”。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值