前言
该节我们一起来认识并熟悉C语言编程里面有哪些数据类型,这是程序构成的重要组成部分。
一、数据类型
著名计算机科学家Nikiklaus Wirth提出的公式“数据结构 + 算法 = 程序”,强调的是数据结构和算法在编程中的重要性。数据结构是存储和组织数据的方式,而算法则是解决问题或执行特定任务的步骤。这个公式表明,只有当数据结构和算法有效地结合在一起,才能创建出有效的程序。
而结构化的程序设计公式“程序 = 算法 + 数据结构 + 程序设计方法 + 语言工具和环境”,更进一步地揭示了编程的复杂性。它强调了除了数据结构和算法之外,程序设计方法、编程语言和环境也同样重要。
在C语言中,数据结构通常以数据类型的形式出现,例如整数、浮点数、字符、布尔值等。这些数据类型提供了存储和操作数据的结构,从而可以创建各种复杂的数据结构,如数组、结构体、联合体等。
数据类型的作用不仅在于为变量分配内存空间大小,还在于提供了一种组织和控制程序行为的方式。正确地选择和使用数据类型是编写高效和可靠代码的关键。总体来说C语言的数据类型有如下图几种,当然此外还有空类型。
二、关键字
C语言的关键字(Keywords)是C语言中预定义的一些标识符,可以理解为固定不变的名称表示,它们有特殊的含义,通常用于实现特定的功能或结构。关键字不能作为变量名或函数名使用。
这些关键字的出现是因为它们有助于简化程序编写和增强程序的可读性和可维护性。通过使用关键字,开发者可以以一种更直观和易于理解的方式表达程序中的意图,同时编译器也能够更好地理解和执行程序中的指令。
三、常量与变量
在C语言中,根据数据是否可以修改,可以将数据分为两大类:常量(Constants)和变量(Variables)。
3.1 常量
常量就是固定不变的数据,根据类型有以下四种:
1 )整型常量:
所有整数(正整数,负整数,零)。如:100,12345,-123,0
2)浮点型常量:
所有小数。如:3.14,0.56
3)字符常量:
普通字符,用单引号括起来的一个字符。(不包括单引号本身) 如:’A’,“1’
4)字符串常量:
用双引号括起来的若干个字符串。(不包括双引号本身) 如:”hello world”
3.2 变量
变量形象的说,是一块能够装数据的小房子,本质的来说,变量就是一块有名字的内存空间。变量在编译时为其分配相应的内存空间,可以通过其名字和地址访问相应内存。定义变量的代码形式: 变量类型 变量名 = 初始值
当你定义一个变量时,你实际上是在为这个容器分配一个名称,并指定它可以存储的数据类型。例如,如果你在C语言中定义一个整数变量,你可以这样做:
int myVariable = 10;
在这个例子中,int 是变量类型,表示这个变量可以存储整数。myVariable 是变量的名字,= 之后的 10 是赋给这个变量的初始值。
你可以通过变量名(在这个例子中是 myVariable)来访问或者操作这个变量所存储的数据。例如,你可以改变它的值:
myVariable = 20;
你也可以获取它的值: int value = myVariable;
在这个例子中,value 将会被赋值为 myVariable 当前的数值,也就是 20。
变量可以被修改,也可以参与运算。当变量被定义之后,自动就开辟出了空间,变量名就代表这片空间了。对于变量来说,有各种各样的类型,根据数据的不同,开辟的内存空间也不相同。例如刚才的代码,定义一个 int 型的变量,那么编译器会为它开辟4个字节的空间。
3.3 变量的类型
变量的类型有很多中,根据数据类型大致可以分为三大类:
1 整数:int 、short、 long
2 小数:float、 double
3 字符:char、 wchar_t
另外还有一个关键字:unsigned 可以修饰整数和字符,可以表示无符号数(就是正数)。变量的类型名,叫类型标识符,也叫类型修饰符。基本数据类型的取值范围如下面所示,注意的是小数类型的数值范围可取正负。
3.4 变量类型的选用
在选择C语言中的变量类型时,确实需要慎重考虑。这不仅仅是编程习惯的问题,也涉及到程序的性能和可移植性。以下是你提到的一些原则和额外的建议:
整数类型:
int:通常,在没有特殊需求的情况下,建议使用int作为整数类型。它在大多数系统上都是基本的整数类型,并且与硬件有很好的支持。
short:short通常用于存储较小范围的整数。如果知道变量的值不会超过-32768到32767的范围,可以使用short来节省内存。但是,如果可移植性是一个考虑因素,并且你希望代码在不同的系统上运行,那么使用int更为安全。
long:long类型通常用于当整数可能超过int的范围时。但是,要记住,long在不同的系统和编译器上可能有不同的长度。在某些系统上,它可能与int一样是32位,而在其他系统上可能是64位。通常建议只在必要时使用long,以避免可移植性问题。
long long:这是一个更大的整数类型,通常用于处理非常大的整数。这个类型也是在不同系统和编译器之间可能有不同的大小。
浮点数类型:
float:float类型通常用于需要单精度浮点数的情况。尽管它的精度可能比double低,但它可以节省内存。
double:在没有特殊需求的情况下,建议使用double作为浮点数类型。它的精度和表示范围通常可以满足大多数需求。
字符类型:
char:对于存储字符数据,可以使用char类型。在ASCII字符集中,这通常是足够的。但是,如果你需要存储Unicode字符或其他特殊字符集,那么应该使用wchar_t类型。
其他考虑因素:
可移植性:当编写可移植代码时,应尽量使用基本的和标准化的数据类型。这包括使用int代替非标准的整数类型,以及使用float和double而不是特定于平台的浮点数类型。
内存使用:在嵌入式系统或内存受限的环境中,选择正确的数据类型以优化内存使用是很重要的。例如,如果一个变量不会超过一个特定的范围,使用short或char可能会更有效。
性能:虽然选择正确的数据类型不会直接提高性能,但它可以帮助优化内存使用,从而间接地提高性能。此外,避免不必要的类型转换也可以提高性能。
清晰和一致:在选择变量类型时,应尽量使代码清晰和一致。选择合适的数据类型可以使代码更易于阅读和理解,特别是对于其他开发者来说。
总结起来,选择C语言中的变量类型时,应考虑可移植性、内存使用、性能和代码清晰度等多个因素。在没有特殊需求的情况下,使用基本的整数类型(如int)和浮点数类型(如double)通常是最佳的选择。对于特殊需求或特定的应用场景,可以选择其他的数据类型来优化内存使用或提高性能。
3.5需要了解的字符类型
3.5.1 字符类型概述
开始之前,先问自己一个问题:1和’1’是一个东西吗?字符类型本质上来说,也是数字。这是必然,因为计算机只能存储数字嘛。有一个美国国家标准协会指定了一个标准,用 0~127 之间的数字代表不同的字符。所以每一个字符都和一个数字一一对应的。美国人制定的这个标准称之为 ASCII。
标准ASCII 码也叫标准ASCII(基础ASCII码),标准ASCII码用一个字节(8位)表示一个字符,并规定其最高位为0,实际只用到7位,码值为00000000~01111111,即 0~127。因此可表示 128 个不同字符 。标准 ASCII 码包括数字 0~9、 26 个大写英文字母、 26 个小写英文字母,以及各种标点符号、运算符号和控制命令符号等。要查看对照关系,可以查看《ASCII字符代码表》。一个字节能表示 0-255,所以存储一个普通的英文字符只需要一个字节,故而 char 也就是1个字节大小。
由于编程语言是外国人发明的,使用广泛的 ASCII表中也就没有非英文使用国家的文字字符。比如像我们中国,汉字字符好几万。于是新的编码规范应运而生,关于编码规范是一个复杂的问题,感兴趣的可以自行搜索。在我们这里,wchar_t 就是用来存储复杂字符的,而且他是两个字节,共有 65536 个状态,基本就够用了。
现在我们就能够回答刚才的问题了,1就是数字1,而字符‘1’就可以看成ascii码“0x31”,也就是二进制00110001。
3.5.2 字符与字符串
char 类型用于存储单字节字符。您可以使用它来存储小写字母,大写字母,数字和特殊字符。在定义时,我们通常使用单引号 ' 来包围字符。例如:
char ch = 'A'; // 正确
char ch2 = "Hello"; // 错误,字符串应该用双引号包围
wchar_t(宽字符)类型用于存储多字节字符,通常用于存储Unicode字符。在定义时,我们需要使用 L 前缀来指示一个宽字符,然后用单引号 ' 来包围字符。例如:
wchar_t ch = L'A'; // 正确
wchar_t ch2 = L"Hello"; // 正确,字符串应该用双引号包围
需要注意的是,wchar_t 的大小取决于系统和编译器,但在大多数现代系统上,一个 wchar_t 通常占用2或4字节。这使得它可以存储大多数Unicode字符。
另外,如果你想存储一个字符串(一系列字符),C 语言中还有一种类型叫做字符串常量,但是没有一个变量能够存储字符串常量。需要借助于字符数组或指针(后面介绍),你需要例如:
char str[] = "Hello"; // 正确,这是一个字符数组
3.5.3 字符型与数字
在C语言中,字符类型(char
)实际上是整数类型的一种特殊形式,它被用于表示ASCII字符。在大多数现代计算机系统中,一个字符被存储为一个字节(8位),而一个char
类型的变量通常也被定义为一个字节。
虽然char
类型主要被用于表示字符,但由于其底层表示为整数,所以也可以用于进行数值计算。然而,需要注意的是char
的数据类型是有符号的,其范围通常是-128到127(对于有符号的char
,这取决于具体的编译器和平台),或者0到255(对于无符号的char
)。
此外,您提到的wchar_t
类型是宽字符类型,主要用于存储Unicode字符。wchar_t
的大小可以根据不同的编译器和平台有所不同,但在大多数现代系统上,一个wchar_t
通常占用2个或4个字节,可以表示的字符范围也相应地更大。在有符号的情况下,wchar_t
的范围通常是-32768到32767。
总的来说,虽然char
和wchar_t
都可以用于表示数字,但它们的大小和表示的字符集都有所不同。在进行数值计算时,需要注意变量的类型和其可能的范围。
四、数据类型转换
4.1 自动类型转换
在C语言中,自动类型转换(也称为隐式类型转换)是一种在表达式中自动进行的类型转换。这种类型转换通常发生在操作符涉及不同的数据类型时,系统会根据需要将它们转换为相同的类型以便进行操作。
以下是C语言中自动类型转换的一般规则:(函数,数组,指针的概念后面介绍)
算术转换:当两个不同类型的数值进行运算时,它们会被转换为相同的类型。如果运算的数据有float型或double型,自动转换成double型再运算,结果为double型。如果运算的数据中无float型或double型,但是有long型,数据自动转换成long 型再运算,结果为long型。如果一个操作数是整型,另一个操作数是浮点型,那么整型会被转换为浮点型。一般来说高位比低位类型数据的转换优先级高。
数组到指针的转换:在表达式中,数组会被自动转换为指向其首元素的指针。
函数到指针的转换:在函数调用中,函数的名称(而不是函数调用表达式)会被自动转换为指向该函数的指针。
从一个类型到另一个类型的转换:这种转换可能发生在赋值操作、函数参数传递、函数返回值等情况中。转换的具体规则取决于源和目标类型的兼容性。
注意,虽然自动类型转换在许多情况下很方便,但也可能导致精度损失、溢出等问题。因此,在使用自动类型转换时需要谨慎。特别是在涉及数值计算和数据处理的场合,通常推荐明确进行类型转换以避免潜在问题。
4.2 强制转换
在C语言中,强制类型转换可以通过使用类型转换运算符来完成。这个运算符用圆括号括起来的目标类型作为前缀,后面跟着要强制转换的表达式,如(类型) 表达式。
例如,如果你有一个浮点数2.5,你想将其强制转换为整数,可以使用以下语法:
int i = (int) 2.5;
这将把2.5转换为整数2,并把结果赋值给变量i。请注意,这种强制类型转换会导致原始浮点数值的小数部分被截断。
强制类型转换还可以用于满足一些运算符对数据类型的特定要求。例如,求余运算符“%”要求其两侧的操作数必须是整型。如果你有两个浮点数,你需要将它们都转换为整型才能进行求余运算:
float a = 7.5;
float b = 3.2;
int result = (int) (a % b); // 正确,result将是2
此外,强制类型转换在处理整数除法时特别有用,因为它可以防止丢失小数部分:
float a = 7.5;
int b = 3;
int result = (int) (a / b); // 正确,result将是2,不会丢失小数部分
需要注意的是,强制类型转换可能会导致数据丢失或范围溢出,因此在使用它时需要小心。
五、标识符
5.1 标识符的命名规则
编程的时候,有许多需要命名的对象,比如函数名,变量名等,这些名称叫做标识符。标识符具有命名规则,标识符的命名规则如下:
1 只能由字母(A~Z,a~z)、数字(0~9)、下划线(_)组成
例:int $abcd = 0; !cde = 0; 错误
2 数字不能开头
例:int 2abcd = 0,45Name = 0; 错误
3 不可以使用关键字
例:int if = 0; int for =0; 错误
4 C语言中的标识符区分大小写
例:int nNumb=0; int nnumb = 0; 为两个不同的变量
5.2 标识符命名规范
我们定义的变量名最好是清晰规范有含义的,而不是用一堆的字母随便堆砌。那么如何算是清晰规范有含义的命名?到目前为止,IT 界已经形成了多种规范,其中有一个牙利命名法。
匈牙利命名法是一种广泛使用的编程命名规范,它的主要目的是使变量和函数的命名更具可读性和可理解性。按照这种规范,变量和函数的名称会以一个或多个小写字母开头,这些字母通常表示变量或函数的类型或用途。接下来是程序员选择的任何名称。
例如,使用匈牙利命名法,变量名可能是类似这样的形式:
如strUserName
,intAge
,floatWeight等等
。这样的名称清晰地表达了变量的类型和用途,使得阅读和理解代码变得更加容易。
然而,也需要注意,虽然匈牙利命名法在很多情况下被广泛使用,但并没有一种标准的、绝对的命名规范在所有的编程社区中被接受。不同的编程语言、不同的开发团队、不同的项目,可能会有不同的命名规范。
总的来说,选择何种命名规范应该根据实际情况来决定,例如团队的编程规范、项目的需求等。同时,保持代码的可读性和清晰性也是非常重要的。