• C语言从入门到精通 第二章(数据的表现形式)


    一、常量和变量

    1、常量

    (1)在程序运行过程中,其值不能被改变的量称为常量,如:

    ①整型常量:如1000、12345、0、-345。

    实型常量

    [1]十进制小数形式,由数字和小数点组成,如0.34、-56.79、0.0。

    [2]指数形式,如12.34e3(代表12.34×103),e可以大写,但需注意e或E之前必须有数字,且e或E后面必须为整数。

    字符常量

    [1]普通字符,用单撇号括起来的一个字符,如’?’、’a’、’1’,字符常量只能是一个字符,不包括单撇号。

    [2]转义字符,是一种特殊形式的字符常量,是以字符“\”开头的字符序列,如换行符’\n’,它们是屏幕上无法显示的“控制字符”,且有其它重要的作用,在程序中也无法用一个一般形式的字符表示,只能采用这样的特殊形式来表示。

    转义字符

    字符值

    输出结果

    \’

    一个单撇号(‘)

    输出单撇号字符’

    \”

    一个双撇号(“)

    输出双撇号字符”

    \?

    一个问号(?)

    输出问号字符?

    \\

    一个反斜线(\)

    输出反斜线字符\

    \a

    警告

    产生声音或视觉信号

    \b

    退格

    将光标当前位置后退一个字符

    \f

    换页

    将光标当前位置移到下一页的开头

    \n

    换行

    将光标当前位置移到下一行的开头

    \r

    回车

    将光标当前位置移到本行的开头

    \t

    水平制表符

    将光标当前位置移到下一个Tab位置

    \v

    垂直制表符

    将光标当前位置移到下一个垂直制表符对齐点

    \o、\oo或\ooo

    其中o代表一个八进制数字

    与该八进制码对应的ASCII字符

    与该八进制码对应的字符

    \xh[h…]

    其中h代表一个十六进制数字

    与该十六进制码对应的ASCII字符

    与该十六进制码对应的字符

    [3]字符常量存储在计算机存储单元中时并不是存储字符本身,而是以其二进制代码(一般采用ASCII码)存储。

    ④字符串常量:如”114boy514”,用双撇号把若干个字符括起来,字符串常量是双撇号中的全部字符(不包括双撇号本身)。

    ⑤符号常量:使用宏定义的常量。(不占用内存空间,往后再详细介绍)

    (2)举例:

    ①例1:

    1. #include
    2. #define PI 3.1415 //宏定义的常量
    3. int main()
    4. {
    5. printf("Hello world\n"); //在屏幕上输出“Hello world”字符串,转义字符’\n’的作用是换行
    6. printf("%d\n", 20); //打印整型常量20
    7. printf("%f\n", 2.1); //打印实型常量2.1
    8. printf("%c\n", 'A'); //打印字符常量'A'
    9. printf("%f\n", PI); //打印符号常量PI
    10. return 0;
    11. }

    ②例2:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #include
    4. int main()
    5. {
    6. printf("%c\n", '\'');
    7. printf("%s\n", "\"");
    8. printf("%d\n", strlen("abcdef"));
    9. // \62被解析成一个转义字符,8不会出现在八进制数里,所以不会被解析为转义字符
    10. //“\62”:62作为八进制数转换为十进制数后作为ASCII码,有对应的字符
    11. printf("%d\n", strlen("c:\test\628\test.c"));
    12. printf("%s", "\x62 \57");
    13. return 0;
    14. }

    2、变量

    (1)变量代表一个有名字的、具有特定属性的一个存储单元,它用来存放数据,也就是存放变量的值。

    (2)与常量不同的是,在程序运行期间,变量的值是可以改变的。

    (3)变量必须先定义再使用,在定义时指定该变量的名字和类型(一个变量应该有一个名字,以便被引用)。

    (4)定义变量的语法:

            <数据类型> <变量名列表>;  //可以一口气定义几个同类型变量(用逗号分隔变量名),且在定义时可以用“=”对变量分别进行初始化(不强制)

    1. #include
    2. int main()
    3. {
    4. char ch = 'A', CH_1; //定义两个字符变量,并对其中一个进行初始化
    5. int AGE_2, age = 20; //定义两个整型变量,并对其中一个进行初始化
    6. int hei, ght; //定义两个整型变量
    7. char number; //定义一个字符变量
    8. printf("%c\n", ch);
    9. printf("%d\n", age);
    10. return 0;
    11. }

    (5)变量名实际上是以一个名字代表的一个存储地址,在对程序编译连接时由编译系统给每一个变量名分配对应的内存地址。从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据

    3、常变量

    (1)C99允许使用常变量,方法是在定义变量时,前面加一个关键字const。定义常变量之后,在变量存在期间其值都不能发生改变,否则无法通过编译,另外在定义常变量时必须对其进行初始化

    (2)常变量与常量的异同是:常变量具有变量的基本属性——有数据类型、占用存储单元,只是不允许改变其值。

    (3)举例:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. #define MAX 10 //#define定义的标识符常量
    4. int main()
    5. {
    6. //字面常量
    7. 3;
    8. printf("%d\n", 3);
    9. //const修饰的常变量
    10. const int num = 4;
    11. //num = 8; const修饰的常变量不能改
    12. int arr[num]; //定义数组时本来是不能使用变量去定义元素个数的,但是常变量可以(数组在后面会详细介绍)
    13. //#define定义的标识符常量
    14. printf("%d\n", MAX);
    15. return 0;
    16. }

    4、标识符

    (1)在计算机高级语言中,用来对变量、符号变量名、函数、数组、类型等命名的有效字符序列统称为标识符,简单地说,标识符就是一个对象的名字。

    (2)C语言规定标识符只能由字母、数字和下划线3种字符组成,且第1个字符必须是字母或下划线

    (3)不允许使用关键字作为标识符的名字!C语言的关键字是编程语言中的保留字,用于特定的语法结构或功能,可以分为以下几类:

    ①数据类型关键字:用于定义变量的类型,如“int”(整型)、“float”(浮点型)、“double”(双精度浮点型)、“char”(字符型)、“struct”(结构体)、“union”(共用体)、“enum”(枚举类型)、“void”(无返回值或无参数的函数)等。

    ②存储类型关键字:用于指定变量的存储方式,如“auto”(自动变量)、“static”(静态变量)、“register”(寄存器变量)、“extern”(外部变量)等。

    ③控制语句关键字:用于控制程序的执行流程,如“if”(条件语句)、“else”(条件语句)、“for”(循环语句)、“while”(循环语句)、“do”(循环语句)、“break”(跳出当前循环)、“continue”(结束当前循环,开始下一轮循环)、“switch”(开关语句)、“case”(开关语句的分支)、“default”(开关语句中的最后分支)、“return”(返回语句)等。

    ④其它关键字。如“const”(只读变量)、“sizeof”(计算数据类型长度)、“typedef”(给数据类型取别名)、“volatile”(说明变量在程序执行中可被隐含地改变)等。

    二、数据类型

    1、C语言允许使用的类型

    (1)所谓类型,就是对数据分配存储单元的安排,包括存储单元的长度(占多少字节)以及数据的存储形式,不同的类型分配不同的长度和存储形式。

    (2)基本类型(包括整型和浮点型)和枚举类型变量的值都是数值,统称为算术类型。算术类型和指针类型统称为纯量类型,因为其变量的值是以数字来表示的。枚举类型是程序中用户定义的整数类型。数组类型和结构体类型统称为组合类型,共用体类型不属于组合类型,因为在同一时间内只有一个成员具有值。函数类型用来定义函数,描述一个函数的接口,包括函数返回值的数据类型和参数的类型。

    (3)不同数据类型的数据在内存中占用的存储单元长度是不同的,使用sizeof关键字可以查看一个数据类型的数据在内存中占用了多少存储空间sizeof的参数可以是具有对应数据类型的变量名,也可以直接是数据类型名,返回一个十进制整数以反映一个数据类型对应的一个数据所占用的字节数)。

    1. #include
    2. int main()
    3. {
    4. //char 字符类型
    5. char ch = 'A'; //向内存申请一段空间存放字符“A”
    6. printf("%c\n", ch); //%c-打印字符格式的数据
    7. printf("char类型占用内存空间大小:%d\n", sizeof(char)); //单位为字节
    8. //int 整型
    9. int age = 20; //向内存申请四个字节存放数据20
    10. printf("%d\n", age); //%d-打印整型十进制数据
    11. printf("int类型占用内存空间大小:%d\n", sizeof(int));
    12. //short int 短整型
    13. printf("short类型占用内存空间大小:%d\n", sizeof(short));
    14. //long int 长整型 long long int 更长的整型
    15. long num = 100;
    16. printf("%d\n", num); //%d-打印整型十进制数据
    17. printf("long类型占用内存空间大小:%d\n", sizeof(long));
    18. printf("long long类型占用内存空间大小:%d\n", sizeof(long long));
    19. //float 单精度浮点型
    20. float f = 5.0f; //不加f会默认为双精度数据,可能会报错
    21. printf("%f\n", f); //%f-打印浮点数字(小数)
    22. printf("float类型占用内存空间大小:%d\n", sizeof(float));
    23. //double 双精度浮点型
    24. double d = 3.14;
    25. printf("%lf\n", d); //%lf-打印双精度浮点数字(小数)
    26. printf("double类型占用内存空间大小:%d\n", sizeof(double));
    27. //%p-以地址的形式打印 %x-打印十六进制数字
    28. //计算机中的单位(从小到大):bit-比特位 byte-字节 KB MB GB TB PB
    29. //1个字节=8个比特位的大小 1MB=1024byte 1GB=1024MB ……
    30. return 0;
    31. }

    2、整型数据

    (1)整型数据的分类:

    ①基本整型(int型):

    [1]编译系统分配给int型数据2个字节或4个字节,这个由具体的C编译系统自行决定。

    [2]int型在存储单元中用整数的补码形式存放。

    [3]在存放整数的存储单元中,最左边的一位是用来表示符号的,如果该位为0表示数值为正,如果该位为1表示数值为负。

    [4]假定现在int型数据的大小为4个字节(比如Visual C++),也就是32位,那么它能存放的数值的范围为-2147483648(-2^{31})\sim 2147483647(2^{31}-1),共2^{32}个整数。

    ②短整型(short int):

    [1]短整型的类型名为short int或short。

    [2]通常会给short int型数据分配2个字节,这样由具体的C编译系统自行决定。

    [3]假定现在short int型数据的大小为2个字节(比如Visual C++),也就是16位,那么它能存放的数值的范围为-32768(-2^{15})\sim 32767(2^{15}-1),共2^{16}个整数。

    ③长整型(long int):

    [1]长整型的类型名为long int或long。

    [2]Visual C++对一个long型数据分配4个字节,也就是32位。

    [3]假定现在long int型数据的大小为4个字节(比如Visual C++),也就是32位,那么它能存放的数值的范围为-2147483648(-2^{31})\sim 2147483647(2^{31}-1),共2^{32}个整数。

    ④双长整型(long long int):

    [1]双长整型的类型名为long long int或long long,这是C99新增的类型,截止至2017年,许多C编译系统尚未实现。

    [2]通常会给long long型数据分配8个字节。

    [3]假定现在long long int型数据的大小为8个字节(比如Visual C++),也就是64位,那么它能存放的数值的范围为-2^{63}\sim (2^{63}-1),共2^{64}个整数。

    (2)整型变量的符号属性:

    ①在实际应用中,有的数据范围只有正值,为了充分利用变量的值的范围,可以将变量定义为无符号类型,只需在类型符号前面加上修饰符unsigned即可

    ②在Visual C++中,整型数据常见的存储空间和值的范围:

    ③对于一个变量,在定义时如果未指定为signed也未指定为unsigned的,默认为有符号类型,也就是默认指定为signed。

    ④有符号类型和无符号类型的存储和输出:

    [1]不管是有符号类型还是无符号类型,在对其进行初始化或者赋值时,编译器首先都会将要赋予的值“翻译”为二进制补码,然后将其存储进变量名对应的空间中,如果补码位数大于存储空间则保留低位、截断高位(影响该数的原值),如果补码位数小于存储空间则用符号位向高位扩展(不影响该数的原值),由于正数的符号位(最高位)为0,所以这并不影响无符号类型的存储。

    [2]以有符号的十进制整数形式输出变量时,是按照补码形式访问变量的,最高位会被视作符号位,然后将其“翻译”为十进制数(也可能是十六进制数或八进制数,这里暂时不做介绍);以无符号的十进制整数形式输出变量时,是按照普通二进制数的形式访问变量,直接将其“翻译”为十进制数。(在Visual C++中,对于不足32位的有符号变量,会发生整型提升,以最高位将自身往高位扩展至32位;对于不足32位的无符号变量,也会发生整型提升,用0将自身往高位扩展至32位)

    1. #include
    2. int main()
    3. {
    4. //32768的二进制补码:00000000 00000000 10000000 00000000
    5. //-32768的二进制补码:10000000 00000000
    6. int a = 32768; //a中的存储情况:00000000 00000000 10000000 00000000
    7. short int b = 32768; //b中的存储情况:10000000 00000000(超出短整型的存储范围,取其补码的前16位存入变量b中,最高位被误当成符号位)
    8. unsigned short int c = -32768; //c中的存储情况:10000000 00000000(无符号整型的二进制代码最高位不是符号位,也认不出10000000 00000000是一个负数的补码)
    9. signed int d = -32768; //d中的存储情况:11111111 11111111 10000000 00000000(补码位数过少,用符号位的数字往后扩展至32位为止)
    10. //以有符号的十进制整数形式输出变量
    11. printf("%d\n", a); //输出正常
    12. printf("%d\n", b); //由于变量b不足32位,发生整型提升,高16位全部补1,接着按补码形式转换为十进制数就是-32768
    13. printf("%d\n", c); //由于变量c不足32位,发生整型提升,高16位全部补0,接着按补码形式转换为十进制数就是32768
    14. printf("%d\n", d); //补码位数扩展不会影响补码本身对应的十进制数,所以输出正常
    15. //以无符号的十进制整数形式输出变量
    16. printf("%u\n", a); //输出正常
    17. printf("%u\n", b); //由于变量b不足32位,发生整型提升,高16位全部补1,接着按普通二进制数的形式转换为十进制数就是4294934528
    18. printf("%u\n", c); //由于变量c不足32位,发生整型提升,高16位全部补0,接着按普通二进制数的形式转换为十进制数就是32768
    19. printf("%u\n", d); //变量d的32位二进制代码按普通二进制数的形式转换为十进制数就是4294934528
    20. return 0;
    21. }

    3、字符型数据

    (1)字符是按其代码(整数)形式存储的,C99把字符型数据作为整数类型的一种,不过字符型数据在使用上有自己的特点。

    (2)字符与字符代码并不是任意写一个字符,程序都能识别的,目前大多数系统采用ASCII字符集,各种字符集基本都包括了127个字符,其中包括:

    ①字母:大写英文字母A~Z,小写英文字母a~z。

    ②数字:数字0~9。

    ③专门符号:29个,有“!”、“#”等。

    ④空格符:空格、水平制表符(Tab)、垂直制表符、换行、换页。

    ⑤不能显示的字符:空(null)字符、警告、回车、退格等。

    (3)字符是以整数形式(字符的ASCII代码)存放在内存单元中的,例如:

    ①大写字母’A’的ASCII代码是十进制数65,二进制形式为1000001。

    ②小写字母’a’的ASCII代码是十进制数97,二进制形式为1100001。

    ③数字字符’0’的ASCII代码是十进制数48,二进制形式为0110000。

    (4)所有127个字符都可以用7位二进制数表示,所以在C语言中,指定1个字节(8位)存储一个字符,字节中的第1位置为0。

    (5)字符变量是用类型符char定义的字符变量。

    在使用或定义字符变量时,可以把0~127之间的一个整数直接赋给字符变量,也可以把用单撇号括起来的一个字符赋给字符变量

    在输出字符变量的值时,可以选择以十进制整数形式输出,也可以选择以字符形式输出

    1. #include
    2. int main()
    3. {
    4. char a; //定义一个字符变量
    5. char b = 'A';
    6. char c = 65;
    7. printf("%c\n", b); //以字符形式输出字符变量b
    8. printf("%d\n", b); //以整数形式输出字符变量b
    9. printf("%c\n", c); //以字符形式输出字符变量c
    10. printf("%d\n", c); //以整数形式输出字符变量c
    11. return 0;
    12. }

    (6)字符类型也属于整型的一种,所以也可以用signed或unsigned对其进行修饰,这么做的意义是,有时需要存储的整数其范围仅仅是0~255,只需一个字节的存储空间即可,这时就可以使用unsigned char类型进行存储。

    (7)几个例子:

    ①例1:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. char a = -1; //(signed) char 有符号,8个bit中有一个位是符号位
    6. signed char b = -1;
    7. unsigned char c = -1; //unsigned char 无符号,8个bit位全用来表示值的大小
    8. //但是这里把-1的补码(11111111)存在c中,而c无符号位,则11111111(二进制)表示255(十进制)
    9. printf("a=%d,b=%d,c=%d", a, b, c);
    10. return 0;
    11. }

    ②例2:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. char a = -128;
    6. printf("%u\n", a); //%u表示以无符号整型的形式输出,-128(十进制)的补码为10000000(二进制)
    7. //但是a是字符型,所以会发生整型提升,变成11111111111111111111111110000000(二进制),由于没有符号位,全部转成整数
    8. return 0;
    9. }

    ③例3:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. char a = 128; //理论上有符号的char是存不进128的,最大只能到127
    6. //128(十进制)的原码为10000000(二进制,无符号)
    7. printf("%u\n", a); //整型提升,变成11111111111111111111111110000000
    8. return 0;
    9. }

    4、浮点型数据

    (1)浮点型数据是用来表示具有小数点的实数的,浮点数类型包括float(单精度浮点型)、double(双精度浮点型)、long double(长双精度浮点型)。

    (2)Visual C++环境下实型数据的有关情况:

    (3)根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:

    ①举例:

    [1]十进制的5.0,写成二进制是101.0 ,相当于1.01\times 2^{2},那么,按照上面的格式可以得出s=0、M=1.01、E=2。

    [2]十进制的-5.0,写成二进制是-101.0 ,相当于-1.01\times 2^{2},那么,按照上面的格式可以得出s=1、M=1.01、E=2。

    有些十进制浮点数无法转换成二进制,比如10.6,这说明浮点数可能并不会被精确存储

    IEEE 754规定,对于32位的浮点数(单精度),最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M;对于64位的浮点数(双精度),最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

    ④IEEE 754对有效数字M的特别规定:

            前面说过1≤M<2 ,也就是说M可以写成“1.xxxxxx”的形式,其中“xxxxxx”表示小数部分。IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的“xxxxxx”部分,比如保存1.01的时候,只保存“01”,等到读取的时候,再把第一位的1加上去,这样做的目的是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

    ⑤IEEE 754对指数E的特别规定:

            首先,E为一个无符号整数(unsigned int),这意味着如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^{10}的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

            指数E从内存中取出还可以再分成三种情况:

            [1]E不全为0或不全为1:浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。比如0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位,则为1.0\times 2^{-1},其阶码为-1+127=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位——00000000000000000000000,则其二进制表示形式为:

            0 01111110 00000000000000000000000

            [2]E全为0:浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为“0.xxxxxx”的小数,这样做是为了表示±0,以及接近于0的很小的数字。

            [3]E全为1:如果有效数字M全为0,表示±无穷大(正负取决于符号位s)。

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. int n = 9; //n的存储情况:00000000000000000000000000001001
    6. float Float = 9.0f; //V形式:1001.0(S=0 E=3 M=1.001)
    7. printf("n的值为:%d\n", n);
    8. printf("Float的值为:%f\n", Float);
    9. //0 00000000 00000000000000000001001 E全为0,表示无穷小
    10. return 0;
    11. }

    (4)对于一个浮点型数据,如果不加以任何修饰,程序会默认将其当作双精度浮点型数据进行处理,虽然这种错误很少会影响程序的运行结果,但可能会影响程序运行结果的精确度。

    ①要让程序识别出一个数据是单精度浮点型数据,可以在其后面添加一个“f”。

    ②要让程序识别出一个数据是双长精度浮点型数据,可以在其后面添加一个“L”。

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. double a = 9.0;
    6. float b = 9.0f;
    7. long double c = 9.0L;
    8. printf("%f\n", a);
    9. printf("%f\n", b);
    10. printf("%f\n", c);
    11. return 0;
    12. }

    5、逻辑型数据

    (1)逻辑型用关键字bool表示,因此又称为bool型(布尔型)。

    (2)逻辑型的取值只包含true和false,它们都是C语言的关键字,其中true对应整数1,表示逻辑真;false对应整数0,表示逻辑假

    (3)布尔类型数据占用1字节(Byte),即8位(bit)空间。

    (4)由于逻辑值对应着整数1或0,所以它也能够像其它整数一样出现在表达式中参与各种整数运算。

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. bool flag = true;
    6. printf("%d\n", flag);
    7. bool Flag = false;
    8. printf("%d\n", Flag);
    9. printf("%d\n", sizeof(bool));
    10. return 0;
    11. }

  • 相关阅读:
    一文理解Cookie、Session
    exception错误处理库学习
    国标GB28181协议视频平台EasyGBS国标平台设备播放断流现象的排查分析及解决
    安卓开发Android studio学习笔记14:用户注册登录(案例演示)
    jar包,引入依赖
    Nginx配置指令
    如何选择VR全景设备,才能拍摄高质量的VR全景?
    深入Linux内核(进程篇)—进程切换之ARM体系架构 简单总结
    画图带你彻底弄懂三级缓存和循环依赖的问题
    【每日一题】535. TinyURL 的加密与解密
  • 原文地址:https://blog.csdn.net/Zevalin/article/details/136432724