第3章 数据和C

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24990189/article/details/89929658

 

目录

3.1 示例程序

3.2 变量与常量数据

3.3 数据:数据类型关键字

3.3.1 整数和浮点数

3.3.2 整数

3.3.3 浮点数

3.4 C语言基本数据类型

3.4.1 int类型

3.4.2 其他整数类型

3.4.3 使用字符:char类型

3.4.4 Bool类型

3.4.5 可移植类型:stdint.h 和 inttypes.h

3.4.6 float、double和long double

3.4.7 复数和虚数类型

3.4.8 其他类型

3.4.9 类型大小

3.5 使用数据类型

3.6 参数和陷阱

3.7 转义序列示例

3.7.1 程序运行情况

3.7.2 刷新输出

3.8 关键概念

3.9 本章小结


3.1 示例程序

#include <stdio.h>
void butler(void);
int main(void){
	float weight;
	printf("Are you worth your weight in platinum?\n");
	scanf("%f",&weight);
	printf("Your weight is %.2f \n",weight);
}
Are you worth your weight in platinum?
123.12345 //按下Enter键(发送换行符)
Your weight is 123.12 

新元素的部分解释:

prinrf()中使用%f来处理浮点值,%.2f中.2用于精确控制输出,指定输出的浮点数只吸纳是小数点后两位。

scanf()中%f说明要读取用户从键盘输入的浮点数,&表明要找到weight变量的地点。

3.2 变量与常量数据

常量(constant)、变量(variable)

3.3 数据:数据类型关键字

按计算机的存储方式,可分为两大基本类型:整数类型和浮点数类型

区分位、字节和字

位(bit),最小存储单位,0或1(即开或关),虽然1位存储的信息有限,但是计算机中位的数量十分庞大,位是计算机内存的基本构建快。

字节(byte),是常用的计算机存储单位,1字节等于8位,8位就有256种可能的0、1组合。通过二进制编码可表示0~255的整数或一组字符。

字(word)是设计计算机时给定的自然存储单位,直到目前的64位,计算机的字长越大,其数据转移越快,允许的内存访问也更多。

3.3.1 整数和浮点数

3.3.2 整数

3.3.3 浮点数

e计数发,3.16E7表示3.16 * 10^7

CPU有专门的浮点处理器

3.4 C语言基本数据类型

3.4.1 int类型

int是有符号整型,可以是正整数、负整数或零,即不含小数点和指数的数作为整数。一般用32bit=8byte存储。

%d为转换说明,由于printf()不寻常的设计,函数的参数树不定,所以要确保转换说明的数量与待打印值的数量相等

十六进制35的位组合(bit pattern)是00110101。十进制数16表示成十六进制是0x10,表示成八进制是020.

需要注意,使用不同的进制是为了方便,不会影响数被存储的方式,因为计算机内部都以二进制进行编码。

#include <stdio.h>

int main(void){
	int x = 100;
	printf("dec = %d; octal = %o; hex = %x\n",x,x,x);
	printf("dec = %d; octal = %#o; hex = %#x\n",x,x,x);
	return 0;
}
dec = 100; octal = 144; hex = 64
dec = 100; octal = 0144; hex = 0x64

3.4.2 其他整数类型

short int、long int、long long int 有符号类型

unsigned int. 16位unsigned int允许的取值范围是0~65535,而不是-32768 ~ 32767

一般而言,long long占64位,long占32位,short占16位,int占16位或32位。

int 类型这么多,如何选择?

计数考虑unsigned,计数不用复数而且表示更大的整数。

另外,long占用的空间比int大的系统,使用long类型会减慢运算速度,因此,如非必要,请不要使用long类型。但是如果在long类型和int类型占用空间相同的及其上编写代码,当确实需要32位整数时,应使用long类型而不是intl类型,以便程序一直打哦6位机上仍然可以正常工作。

在int为16位,long为32位的系统中,会把7作为16位存储,把7L作为32位存储

整数溢出问题:

当能表示的最大值时,会重新从起始点开始。当i超出其相应类型所能表示的最大值时,系统并未同志用户,因此,在编程时必须自己注意。

#include <stdio.h>

int main(void){
	int i = 2147483647; //31
	unsigned int j = 4294967295;//32
	printf("%d %d %d\n",i,i+1,i+2);
	printf("%u %u %u\n",j,j+1,j+2);
	return 0;
}

 

2147483647 -2147483648 -2147483647
4294967295 0 1
#include <stdio.h>
int main(void)
{
    unsigned int un = 3000000000; /* system with 32-bit int */
    short end = 200;              /* and 16-bit short       */
    long big = 65537;
    long long verybig = 12345678908642;
    
    printf("un = %u and not %d\n", un, un);
    printf("end = %hd and %d\n", end, end);
    printf("big = %ld and not %hd\n", big, big);
    printf("verybig= %lld and not %ld\n", verybig, verybig);
    
    return 0;
}
un = 3000000000 and not -1294967296
end = 200 and 200
big = 65537 and not 1
verybig = 12345678908642 and not 1942899938

无符号变量un,使用%d会生成负值!其原因是30000000000与-1294967296在系统内存中的内部表示完全相同。告诉printf()是无符号数打印。

在printf()中无论指定以short(%d)还是int(%d)打印,打印出来的值都相同,这是因为C编译器把short类型的值自动转换成int类型的值,因为int类型别认为计算机处理整数时最搞笑的类型。

65537以二进制格式写成32位数00000000000000001000000000001,使用%hd,printf()只会查看后16位,所以显示是1.

预测类似,%ld只会看是存储在后32位的值。

 

3.4.3 使用字符:char类型

1.字符常量和初始化

char类型存储字符(字母、标点符号),从技术层面,char是整数型。因为char类型实际上存储的是整数而不是字符。计算机使用数字编码来处理字符,即特定的整数表示特定的字符。通用的是ASCII编码,其范围位0~127,只需要7位二进制数即可表示。A代表65,char类型被定义为8位的存储单元。

许多字符集都超过了127,甚至多于255。

char grade = 'A';//字符常量
char grade = A;  //变量
char grade = “A”;//字符串
char grade = 65;//字符常量

用单引号扩起来的单个字符称为字符常量(character constant),编译器一经发现‘A’,就会将其转换成相应的代码值。编译器会认为A是变量,“A”是字符串

注意后面的写法,65是字母是A对应的ASCII码,即将A赋值给grade,但是这养的前提是系统使用了ASCII码,所以用‘A’是最合适的选择,不在ASCII码系统也有效。

奇怪的现象,C语言将字符常量视为Int类型而非char类型,在int为32位、char为8位的ASCII系统中,本应数值65存储在32位存储单元中,但是现在可以存储在8位的存储单元中(grade)中。字符常量‘FATE’,把4个独立的8位ASCII码存储在一个32位存储单元中,如果把这样的字符常量赋值给char类型grade,只最后8位有效,即‘E’

2.非打印字符

3.打印字符

注意:printf()函数的转换说明决定了数据的显示方式,而不是数据的存储方式。

4.有符号还是无符号

另外,char类型位有符号类型,范围-128 ~ 127。无符号类型为0 ~255。具体查阅“limits.h”

3.4.4 Bool类型

也是一种整数类型,1表示true,0表示false,占用1位存储空间。

3.4.5 可移植类型:stdint.h 和 inttypes.h

使用int32_t编写程序,并包含stdint.h头文件时,编译器会把int或long替换成位当前系统匹配的类型。这种类型别名为精确宽度整数类型(exact-width integer type)

如果系统不支持,系统提供第2类别名集合,保证所表示类型一定是至少有指定宽度的最小整数类型,称为最小宽度类型(minimum width type),如int_least8_t是可容纳8位有符号整数值的类型中宽度最小的类型的一个别名。

第3类别名集合位,最快最小宽度类型(fastst minimum width type)被定义为系统中对8位有符号值而言运算最快的整数类型的别名。

如果要打印int32_t类型的值,有些需要%d,有些需要%ld,怎么办?在inttypes.h头文件中定义了PRId32字符串宏,代表打印32位有符号值的合适转换说明。

/* altnames.c -- portable names for integer types */
#include <stdio.h>
#include <inttypes.h> // supports portable types
int main(void)
{
    int32_t me32;     // me32 a 32-bit signed variable
    
    me32 = 45933945;
    printf("First, assume int32_t is int: ");
    printf("me32 = %d\n", me32);
    printf("Next, let's not make any assumptions.\n");
    printf("Instead, use a \"macro\" from inttypes.h: ");
    printf("me32 = %" PRId32 "\n", me32);    
    printf("me32 = %d\n", me32);
    return 0;
}
First, assume int32_t is int: me32 = 45933945
Next, let's not make any assumptions.
Instead, use a "macro" from inttypes.h: me32 = 45933945

3.4.6 float、double和long double

默认情况下,编译器假定浮点型常量是double类型的精度,使用f或F后缀可覆盖默认设置位float类型。使用l或L后缀使得数字位long duble类型。

printf()中%f转换说明打印十进制计数法的float和double类型浮点数,用%e打印指数计数法的浮点数,%a打印十六进制格式的浮点数

/* showf_pt.c -- displays float value in two ways */
#include <stdio.h>
int main(void)
{
    float aboat = 32000.0;
    double abet = 2.14e9;
    long double dip = 5.32e-5;
    
    printf("%f can be written %e\n", aboat, aboat);
    // next line requires C99 or later compliance
    printf("And it's %a in hexadecimal, powers of 2 notation\n", aboat);
    printf("%f can be written %e\n", abet, abet);
    printf("%Lf can be written %Le\n", dip, dip);
    
    return 0;
}
32000.000000 can be written 3.200000e+04
And it's 0x1.f4p+14 in hexadecimal, powers of 2 notation
2140000000.000000 can be written 2.140000e+09
0.000053 can be written 5.320000e-05
4008175468544.000000 

上溢(overflow)与下溢(underflow)在cmu213那门课中详细讲到。

/* floaterr.c--demonstrates round-off error */
#include <stdio.h>
int main(void)
{
    float a,b;
    
    b = 2.0e20 + 1.0;
    printf("%f \n", b);
    a = b - 2.0e20;
    printf("%f \n", a);
    
    return 0;
}
200000004008175468544.000000 
4008175468544.000000 

计算机缺少足够的小数位来完成正确的运算。float需要保证有足够的精度来完成计算。

3.4.7 复数和虚数类型

C语言复数类型:float _Complex、double _Complex、long double _Complex

3.4.8 其他类型

3.4.9 类型大小

sizeof是C语言的内置运算符,以字节为单位给出指定类型的大小。C99和C11提高%zd转换说明匹配sizeof的返回类型

//* typesize.c -- prints out type sizes */
#include <stdio.h>
int main(void)
{
    /* c99 provides a %zd specifier for sizes */
    printf("Type int has a size of %zd bytes.\n", sizeof(int));
    printf("Type char has a size of %zd bytes.\n", sizeof(char));
    printf("Type long has a size of %zd bytes.\n", sizeof(long));
    printf("Type long long has a size of %zd bytes.\n",
           sizeof(long long));
    printf("Type double has a size of %zd bytes.\n",
           sizeof(double));
    printf("Type long double has a size of %zd bytes.\n",
           sizeof(long double));
    return 0;
}
Type int has a size of 4 bytes.
Type char has a size of 1 bytes.
Type long has a size of 8 bytes.
Type long long has a size of 8 bytes.
Type double has a size of 8 bytes.
Type long double has a size of 16 bytes.

3.5 使用数据类型

float pi = 3.1415926536;
printf("%f",pi);
3.141593

C只保证float类型的前6位精度。

3.6 参数和陷阱

C语言通过函数原型机制肩擦好函数调用时参数的个数和类型是否正确,但是该机制对printf()和scanf()不起作用,因为这两个函数的参数个数可变。

/* badcount.c -- incorrect argument counts */
#include <stdio.h>
int main(void)
{
    int n = 4;
    int m = 5;
    float f = 7.0f;
    float g = 8.0f;
    
    printf("%d\n", n, m);    /* too many arguments   */
    printf("%d %d %d\n", n); /* too few arguments    */
    printf("%d %d\n", f, g); /* wrong kind of values */
    
    return 0;
}
badcount.c:10:23: warning: data argument not used by format string [-Wformat-extra-args]
    printf("%d\n", n, m);    /* too many arguments   */
           ~~~~~~     ^
badcount.c:11:17: warning: more '%' conversions than data arguments [-Wformat]
    printf("%d %d %d\n", n); /* too few arguments    */
               ~^
badcount.c:12:23: warning: format specifies type 'int' but the argument has type 'float' [-Wformat]
    printf("%d %d\n", f, g); /* wrong kind of values */
            ~~        ^
            %f
badcount.c:12:26: warning: format specifies type 'int' but the argument has type 'float' [-Wformat]
    printf("%d %d\n", f, g); /* wrong kind of values */
               ~~        ^
               %f
4 warnings generated

3.7 转义序列示例

/* escape.c -- uses escape characters */
#include <stdio.h>
int main(void)
{
    float salary;
    
    printf("\aEnter your desired monthly salary:");/* 1 */
    printf(" $_______\b\b\b\b\b\b\b");             /* 2 */
    scanf("%f", &salary);
    printf("\n\t$%.2f a month is $%.2f a year.", salary,
           salary * 12.0);                         /* 3 */
    printf("\rGee!\n");                            /* 4 */
    
    return 0;
}

\r使得光标回到当前行的起始处,然后打印Gee! 然后\n换行

Gee!    $111.00 a month is $1332.00 a year.

3.7.1 程序运行情况

3.7.2 刷新输出

3.8 关键概念

浮点数和整数在本质上不同,其存储方式和运算过程有很大区别,即使两个32位存储单元存储的位组合完全相同,一个解释位float类型,一个解释为long类型,这两个相同的位组合表示的值也完全不同。

3.9 本章小结

猜你喜欢

转载自blog.csdn.net/qq_24990189/article/details/89929658
今日推荐