《C语言程序设计》一2.2 常量、数据的存储与数据类型

简介: 本节书摘来自华章出版社《C语言程序设计》一 书中的第2章,第2.2节,作者:赵宏 陈旭东 马迪芳,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.2 常量、数据的存储与数据类型

2.2.1 基本数据类型

数据是程序加工、处理的对象,也是加工、处理的结果,所以数据是程序设计中所要涉及和描述的主要内容。程序所能处理的基本数据对象被划分成一些组,或者说是一些集合。属于同一集合的各数据对象都具有同样的性质,程序设计语言中具有这样性质的数据集合称为数据类型。
所有数据都属于某种类型。一个数据的类型决定了这个数据在内存中的存储形式、取值范围和能够对它进行的操作。
C/C++ 中的数据类型大致可以分为两大类:第一类是基本数据类型,基本数据类型是系统预定义的类型,包括整型、浮点型(实型)和字符型;第二类是非基本数据类型,即自定义数据类型,包括数组、结构体、共用体、枚举类型和指针类型。本章介绍几种基本数据类型,其他数据类型将在以后各章陆续介绍。图2-1给出了这些数据类型。

image

基本数据类型是基元,所有的数据类型都建立在基本数据类型之上。C/C++语言的基本数据类型有以下几个:
int:整型
char:字符型
float:单精度浮点型
double:双精度浮点型
long double:长双精度浮点型
另外,在基本数据类型的基础上附加一些限定词,得到扩充的数据类型。short、long可以应用到整型,unsigned可以应用到整型和字符型:
short int(或short):短整型
long int(或long):长整型
unsigned int:无符号整型
unsigned short:无符号短整型
unsigned long:无符号长整型
unsigned char:无符号字符型
1.整型
数据的取值范围服从数学式子2n,其中n是这种类型所占内存位数,例如,如果int型是16位,它的数据取值范围为-2n~2n -1,即-32 768~32 767。无符号的数总是正数或零,而unsigned int型数据取值范围为0~2n +1-1,即0~65 535。
ANSI C标准没有规定以上各类数据所占内存位数,只要求short型数据不长于int型,而long型不短于int型,具体如何实现,由各编译系统决定。表2-1列出了ANSI C标准定义的整型数据的最小取值范围。
image

2.浮点型
浮点型数据也称为实数,可以是数字0.0和包含小数点的正数或负数。
C语言支持三种浮点数据类型:浮点型(也称单精度型(float))、双精度型(double)和长双精度型(long double)。这些数据类型之间的差别是编译器为每种类型分配的存储数量。一般情况下,为双精度浮点数采用的存储数量是浮点数采用的数量的两倍,这使双精度浮点数的精度大约是浮点数的两倍。使用sizeof(类型)可以显示你的编译器为每种数据类型提供的存储数量(字节数)。
当前的C编译器所提供的float型在内存中占用4个字节(32位),提供7位有效数字,可能的取值范围为-10-38~1038;double型数据占8个字节,提供15~16位有效数据,可能的取值约为-10-308~10308。浮点型数据的存储符合IEEE浮点数格式,如float型数据,1位用于符号,8位用于指数,23位用于基数。
3.字符型
字符型数据用于存储单个字符,存储时占用8位,它实际存储的是字符对应的ASCII码(American Standard Code for Information Interchange,美国标准信息交换码)。如一个char型数据‘A’,其ASCII码为65,故实际存储的内容是65。char型数据取值范围为-128~127,unsigned char型数据取值范围为0~255。字符有符号或无符号是依赖于机器的,但是可打印的字符总是正的。
由于在内存中字符型数据是以ASCII码形式存放的,其形式与整型类似,因而在C语言中,字符型数据与整型数据可以通用,字符型数据的所有性质与一字节整型量相同。

2.2.2 常量

在程序运行过程中其值不能被改变的量称为常量。本节介绍整型常量、实型常量、字符常量、字符串常量和符号常量。
1.整型常量
整型常量即整数。一个整型常量如123即为int型。长整型常量在后面加字母“l”或“L”,如123456789L,如果一个整型数超过了int类型的范围就会被当成一个long int。无符号常量在后面加上“u”或“U”,后缀为“ul”或“UL”表明是无符号长整型unsigned long。
整型常量可以使用三种形式表示:十进制数、八进制数、十六进制数。每种进制形式的数据都有特殊标记。
1)十进制数,如128、-60、0。
2)八进制数,以0开始的数据是八进制数,如0123代表八进制数123,即十进制数83。
3)十六进制数,以0x开始的数是十六进制数,如-0x128代表十六进制数-128,即十进制数-296。
2.实型常量
实型常量又称实数或浮点数。实数有两种表示形式:
1)十进制形式。它由三部分组成:整数部分、小数点、小数部分,当整数或小数部分为0时可以省略,但小数点不能省略。它适合于表示不太大或不太小的数,如128.0、.128、128.5、128.、0.0等都是十进制数形式。
2)指数形式。它由三部分组成:尾数、字符e(或E)、指数。它适用于表示较大或较小的数。e之前必须有数字,且e后面的指数必须为整数,如128e2或128E2都代表128×102。
如果实型常量后缀是“f”或“F”,则被当成float型,如果实型常量后缀是“l”或“L”,则被当成long double型,否则,C语言编译系统总是将实型常量处理成双精度型的。
3.字符常量
字符常量是用单引号括起来的一个字符,如‘A’、‘a’、‘?’、‘0’等。字符常量的值是机器字符集中字符的数字值,如字符常量‘0’,其ASCII码为48,所以存储的实际内容为48。程序中字符常量通常用于字符之间的比较,也可以像其他整型数一样参与运算,这在程序设计中处理字符时十分有用,如要将小写字母转换成大写字母,只需减去32即可。
字符常量中不包括“’”字符和换行等符号,为表示这些符号,字符常量还有另外一种形式——转义字符形式,由一对单引号中的转义字符组成,而转义字符是一组以“”开头的特殊字符序列,用这种方法可以表示任何可输出的字母字符、专用字符、控制字符和图形字符,如表2-2所示。
image

在程序prg2-1.c中在打印函数的最后一个字符使用了转义字符n,这样可以保证使屏幕光标移到下一行开头。
【例2-2】 转义字符的使用。

/*程序名:prg2-2.c*/
/*功能:使用转义字符控制数据的输出*/
#include<stdio.h>

int main()
{
   char c1 = 'A', c2 = '\101';

   printf("a\tbc\tABC\n");
   printf("xyz\t%c,%c" , c1 ,c2);

   return 0;
}

程序中第一个printf()函数首先在第1行第1列打印字母a,然后遇到t,它的作用是制表符(横向跳格),使屏幕光标移到下一制表位。系统把一行分为10个输出区,每个输出区占8列。下一个输出位置即从第9列开始输出,所以在第9列到第10列上输出bc,之后又是t,跳到第17列,在第17列到第19列输出ABC,n的作用是回车换行。第二个printf()函数首先在第2行第1列到第3列输出xyz,然后跳到下一个输出区,在第9列上输出A,然后输出一个逗号,再输出A,因为转义字符'101'代表的ASCII码是65,对应的是字符‘A’。程序运行结果为:

a    bc    ABC
xyz   A,A

4.字符串常量
字符串常量是由一对双引号括起来的字符序列,例如:

"How do you do."

双引号不是字符串的一部分,只起定界的作用。
字符串常量在编译时可以被连接起来,例如程序

int main()
{   
   printf("This is my first program in C/C++.\n");
   return 0;
}

输出结果为:

This is my first program in C/C++.

也可以写成:

int main()
{
   printf("This is my first program");
   printf("in C/C++.\n");
   return 0;
}

输出结果相同,这对把长字符串分割成几行是很有用的。
C/C++语言中,字符串常量是作为一个字符数组来处理的,字符串在存储时末尾被系统自动加上字符‘0’,因此物理存储的字符串长度比双引号中的字符数多1个。转义字符‘0’为空操作,它既不引起任何控制动作,也不会显示出来,但系统可以据此判断一个字符串是否结束。
要仔细区分字符常量和只包含一个字符的字符串常量,如‘x’与“x”,虽然都只有一个字符,但在内存中的情况是不同的。‘x’在内存中占一个字节,是一个整数,可以产生字符x在机器字符集中的数字值,“x”在内存中占两个字节,包含字符x和转义字符‘0’。

‘x’    x    
                                      “x”    x    \0

5.符号常量
前面介绍的几种类型的常量从字面形式就可以判别出来,如123为整型常量,0.65为实型常量,‘A’为字符型常量,“CHINA”为字符串常量。也可以用一个标识符代表一个常量,称为符号常量。
【例2-3】 符号常量的使用。

/*程序名:prg2-3.c*/
/*功能:符号常量的使用,计算圆的周长和面积*/
#include<stdio.h>
#define  PI  3.14159       /*定义符号常量PI的值为3.14159*/
int main()
{   
   float r, s, area;

   scanf("%f", &r);

   s = 2 * PI * r;
   area = PI * r * r;

   printf("s=%7.2f, area=%7.2f" , s , area);

   return 0;
}

程序中定义了一个符号常量PI来代表常量3.141 59,以后程序中PI就代表3.141 59,可以和常量一样使用。与变量不同,符号常量的值在程序中不能再改变。在程序中使用符号常量代替具有一定意义的常量,增加了程序的可读性、可理解性,易于程序的修改。当程序中某个符号常量需要修改时,只须修改符号常量的定义语句即可,避免了一个常量多处修改中因失误造成的不一致的错误。

#define是编译预处理语句,有关内容详见8.2节。

2.2.3 数据的存储

1.变量和内存的概念
变量是指程序运行过程中保存变化数据的内存单元,与数学中的变量不同。数学中的变量表示未知量,通过解方程求值。程序中的变量只是系统分配的内存单元,用来存放变化的数据。在程序prg2-1.c中定义了a、b、c、s和area等变量,对于每个变量,编译系统会在编译时为其分配相应的内存,所以这些变量名实际对应计算机内存中的地址,通过编程可以把数据保存到这些地址中,也可以从这些地址中读取数据。
在程序prg2-1.c中执行下列语句:

scanf("%f,%f,%f", &a, &b, &c);

“&”为取址运算符,即将用户输入的值存入a、b、c所对应的地址中。假设输入的数据为3、4、5,则内存中a对应的地址中存放3,b对应的地址中存放4,c对应的地址中存放5。

a    3
                                                                  b    4
                                                                  c    5

程序得到a、b、c的值后,对其进行运算:

s = (a + b + c)/2;

该语句从a、b、c对应的地址中读取到3、4和5,进行运算,然后把和值存放到s变量对应的地址中,这时,s中原来的值就被新值覆盖掉了,而a、b、c变量的值和计算之前一样,虽然被使用,但并没有丢失。
变量在程序运行过程中可以不断发生变化,但瞬时只能存放一个值。从变量中读取数据不会破坏变量的值,但是向变量中写数据时将用新数据替换原来的数据。
2.变量定义和赋初值
所有的变量必须先定义其类型,然后才能使用。一个定义中可以包含一个或多个同类型的变量,例如:

int total;                    /*指定total为整型变量*/
float width , length;              /*指定width、length为单精度实型变量*/
double area;                      /*指定area为双精度实型变量*/
char c1 , c2;                     /*指定c1、c2为字符型变量*/

程序中需要对一些变量预先设置初值,即变量可以在定义时进行初始化,例如:

int total = 0, i;                 /*指定total,i为整型变量,total的初值为0*/
int a = 5 , b = 5 , c = 5;         /*指定a、b、c为整型变量,a、b、c的初值为5*/
float esp = 0.001;                 /*指定esp为单精度实数,esp的初值为0.001*/
char c = 'a';                   /*指定c为字符型变量,c的初值为‘a’*/

变量必须先定义后使用的目的是:
1)可以保证程序中变量名使用的正确性。如已定义了一个变量count,但在程序中却写成了cuont,在编译时先检查变量名的合法性,发现cuont未被定义过,按出错处理,因而可以帮助人们查找拼写错误。
2)系统根据变量的类型为变量在内存中开辟存储单元。例如,变量a定义为short,系统会为变量a分配两个字节的内存,可以存放一个整数,变量x定义为float,则系统为变量x分配4个字节的内存,可以存放一个实数。
3)变量类型确定后,也就确定了变量的取值范围和可以对其进行的运算。
3.变量命名规则
定义一个变量,即给变量一个名字和数据类型。高级语言中,用来表示变量名、符号常量名、数组名、函数名等的有效字符序列称为标识符。
标识符由字母、数字和下划线“_”三种字符组成,且第一个字符必须为字母或下划线。C语言是区分大写字母和小写字母的,因此x与X是两个不同的名字。一般用小写字母作为变量的名字,而用大写字母作为符号常量的名字。
C标识符的长度无统一的规定,一般不超过128个字符。
C语言中的关键字(也称为保留字)是编程语言为某一特定用途而预先定义的一个字,并且关键字只能用特定的方式用于它的预先的用途,如if、int、float等有专门的用途,不能用这些名字作为变量的名字,否则编译代码时将产生错误。注意,关键字必须用小写。
给变量起名时应做到见名知意,用有意义的单词作为变量的名字,以增强程序的可读性。一般局部变量用短名字,特别是循环变量,而外部变量用长名字。

相关文章
|
2月前
|
存储 人工智能 程序员
一文彻底搞清楚C语言的数据类型和变量
本文介绍了数据类型(基本、构造、指针、空类型)、变量(使用、命名规则、作用域)和常量(字面、符号、枚举、表达式),帮助初学者理解编程基础概念。坚持学习,定能创造奇迹!
286 1
一文彻底搞清楚C语言的数据类型和变量
|
3月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
164 16
|
3月前
|
算法 C语言
【C语言程序设计——循环程序设计】求解最大公约数(头歌实践教学平台习题)【合集】
采用欧几里得算法(EuclideanAlgorithm)求解两个正整数的最大公约数。的最大公约数,然后检查最大公约数是否大于1。如果是,就返回1,表示。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。作为新的参数传递进去。这个递归过程会不断进行,直到。有除1以外的公约数;变为0,此时就找到了最大公约数。开始你的任务吧,祝你成功!是否为0,如果是,那么。就是最大公约数,直接返回。
137 18
|
3月前
|
Serverless C语言
【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】
根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码,求解出数值x的平方根;运用迭代公式,编写一个循环程序,求解出数值x的平方根。注意:不能直接用平方根公式/函数求解本题!开始你的任务吧,祝你成功!​ 相关知识 求平方根的迭代公式 绝对值函数fabs() 循环语句 一、求平方根的迭代公式 1.原理 在C语言中,求一个数的平方根可以使用牛顿迭代法。对于方程(为要求平方根的数),设是的第n次近似值,牛顿迭代公式为。 其基本思想是从一个初始近似值开始,通过不断迭代这个公式,使得越来越接近。
93 18
|
3月前
|
C语言
【C语言程序设计——循环程序设计】统计海军鸣放礼炮声数量(头歌实践教学平台习题)【合集】
有A、B、C三艘军舰同时开始鸣放礼炮各21响。已知A舰每隔5秒1次,B舰每隔6秒放1次,C舰每隔7秒放1次。编程计算观众总共听到几次礼炮声。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。开始你的任务吧,祝你成功!
91 13
|
3月前
|
存储 安全 C语言
【C语言程序设计——选择结构程序设计】预测你的身高(头歌实践教学平台习题)【合集】
分支的语句,这可能不是预期的行为,这种现象被称为“case穿透”,在某些特定情况下可以利用这一特性来简化代码,但在大多数情况下,需要谨慎使用。编写一个程序,该程序需输入个人数据,进而预测其成年后的身高。根据提示,在右侧编辑器补充代码,计算并输出最终预测的身高。分支下的语句,提示用户输入无效。常量的值必须是唯一的,且在同一个。语句的作用至关重要,如果遗漏。开始你的任务吧,祝你成功!,程序将会继续执行下一个。常量都不匹配,就会执行。来确保程序的正确性。
167 10
|
3月前
|
小程序 C语言
【C语言程序设计——基础】顺序结构程序设计(头歌实践教学平台习题)【合集】
目录 任务描述 相关知识 编程要求 测试说明 我的通关代码: 测试结果: 任务描述 相关知识 编程编写一个程序,从键盘输入3个变量的值,例如a=5,b=6,c=7,然后将3个变量的值进行交换,使得a=6,b=7,c=5。面积=sqrt(s(s−a)(s−b)(s−c)),s=(a+b+c)/2。使用输入函数获取半径,格式指示符与数据类型一致,实验一下,不一致会如何。根据提示,在右侧编辑器补充代码,计算并输出圆的周长和面积。
98 10
|
3月前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
88 3
|
3月前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
76 2
|
3月前
|
存储 C语言
【C语言程序设计——循环程序设计】利用数列的累加和求 sinx(头歌实践教学平台习题)【合集】
项的累加和,一般会使用循环结构,在每次循环中计算出当前项的值(可能基于通项公式或者递推关系),然后累加到一个用于存储累加和的变量中。在C语言中推导数列中的某一项,通常需要依据数列给定的通项公式或者前后项之间的递推关系来实现。例如,对于一个简单的等差数列,其通项公式为。的级数,其每一项之间存在特定的递推关系(后项的分子是其前项的分子乘上。,计算sinx的值,直到最后一项的绝对值小于。为项数),就可以通过代码来计算出指定项的值。对于更复杂的数列,像题目中涉及的用于近似计算。开始你的任务吧,祝你成功!
107 6