基础2.2拓展: 基本数据类型 +运算符+变量

本节课理论知识较多。

  1. C语言有哪些数据类型?有哪些整数类型?有哪些浮点类型?
  2. 各种数据类型如何表示?输入输出格式化有哪些?
  3. 各种类型大小是多少?范围是多少?
  4. 如何选择整型类型和浮点类型?

1. 数据类型

学习是一个日积月累的过程,从多模仿,到多看多想,最后到多用。

数值类型分为整型(整数)和浮点型(小数)。按照表示数字范围的从大到小

  • 整数分为五类:字符型(char)、短整型(short)、整型(int)、长整型(long)和长长整型(long long)
  • 浮点型分三类:单精度型(float)、双精度型(double)和长双精度型(long double)

1.1 获取类型大小

关键字sizeof:查看变量或者类型大小

   int n;
    printf("%d",sizeof(int));
    printf("%d",sizeof(n));

上面的括号不是必须的,但是建议带上。所以也可以如下表示:

  int n;
    printf("%d",sizeof int);
    printf("%d",sizeof n);
    

2.2 各种类型的大小

完整代码见001_type.c

#include <stdio.h>

int main(){
printf("sizeof(char)=%d\n",sizeof(char));
printf("sizeof(short)=%d\n",sizeof(short));
printf("sizeof(int)=%d\n",sizeof(int));
printf("sizeof(long)=%d\n",sizeof(long));
printf("sizeof(long long)=%d\n",sizeof(long long));
printf("sizeof(float)=%d\n",sizeof(float));
printf("sizeof(double)=%d\n",sizeof(double));
printf("sizeof(long double)=%d\n",sizeof(long double));
}

在编译命令加上选项-m32再试一下。

通常有些类型大小并不是固定的,计算机硬件、操作系统和编译器都会影响类型的大小。通常类型大小有如下规律:

char < short < int < float < double  
int <= long <= long long

在常用的计算机硬件和操作系统中,各种类型的大小如下表所示:

2.3 字节

sizeof获得数据的单位是Byte(字节)。Byte(字节)是计量存储容量的一种计量单位,一个字节是8位二进制,可容纳256个数字。一个ASCII字符就是一个字节。

除了Byte(字节),还有其他常用存储容量单位

No.单位说明
1bit(比特/位)计算机中的最小数据单位,1个Byte(字节)=8个bit(比特/位)
2word(字)计算机CPU一次操作处理实际数据最大位数,我们常说的32/64位就是计算机的字。
3KB1KB=1024B
4MB1MB=1024KB
5GB1GB=1024MB
6TB1TB=1024GB

有时,我们用B表示Byte(字节),用b表示bit(比特/位),注意两者区别。

2.4 输入输出格式化

No.类型占位符
1char%c
2short%hd
3int%d
4long%ld
5long long%lld
6float%f
7double%lf
8long double%Lf

double的输入占位符必须是%lf,输出占位符可以是%f


2. 整数类型

2.1 表示范围

每种数据类型大小不同,各自表示数据范围也不同。下面的常用类型的范围。

No.类型数字范围表示
1char-128~127-27~27-1
2short-32 768~32 767 约±3万-2^15 到 2^15-1
3int-2 147 483 648~2 147 483 647 约±21)]亿-2^31~ 2^31-1
4long long-9 223 372 036 854 775 808~9 223 372 036 854 775 807 约±10^20]亿-2^63~ 2^63-1

上面的是通常范围(32位下),实际上有些情况略有出入。总之,类型的表示范围与类型大小存在如下关系:
在这里插入图片描述

n是类型大小。

2.2 无符号整型

在一些特殊情况下,数据只用0和整数,不存在负数,这时可以使用无符号整型unsigned。无符号整型只是在原来的整型前加上关键字unsigned。因为没有负数,所以数值的表示范围扩大了一倍。

No.类型数字范围表示
1unsigned char0~2550~2^8-1
2unsigned short0~65 535约±6万0~2^16-1
3unsigned int0~4 294 967 295约±43亿0~2^32-1
4unsigned long long0~18 446 744 073 709 551 6150~2^64-1

类型的表示范围与类型大小存在如下关系:

在这里插入图片描述

n是类型大小。

输入输出无符号整型格式

No.类型占位符
1char%u
2short%hu
3int%u
4long%lu
5long long%llu

2.3 整型类型选择

整型类型很多,通常遵循下面的使用规则:

  1. 大多数情况下使用int
  2. 如果int范围不够,使用long long
  3. 避免使用long
  4. 谨慎使用unsigned

3. 浮点类型

3.1 浮点数的范围

注意:正数除以0,结果为正无穷(-inf);
负数除以0,结果为负无穷;(-inf)
0/0 结果为 不存在(nan)
完整代码见002_divideZero.c

运行下面程序,分析执行结果:

#include <stdio.h>

int main(){
    printf("1.0/0.0  = %f\n",1.0/0.0);  //inf
    printf("-1.0/0.0 = %f\n",-1.0/0.0);//-inf
    printf("0.0/0.0  = %f\n",0.0/0.0);//-nan
    return 0;
}

当浮点数超出可表示的范围,会有如下值。

No.输出含义
1inf表示正无穷大
2-inf表示负无穷大
3nan不存在

3.2 浮点数的精度

  • 设计上的精度问题

计算机浮点数存在精度问题。
注意:float最大表示6——7位:小数点前面7位或者小数点后面7位,第八位四舍五入或者随机值
float最大:15-16

float  f = 123456789.0;
        double d = 123456789.0;
        printf("f=%f\n" ,f);  //123456792.0
        printf("d=%lf\n",d); //123456789.0
运行下面程序,分析执行结果:

完整代码见003_float.c

   #include <stdio.h>
    
    int main(){
        float  f = 123456789.0;
        double d = 123456789.0;
        printf("f=%f\n" ,f);
        printf("d=%lf\n",d);
        return 0;
    }
No.类型数字范围有效数字
1float-3.4E+38~`3.4E+386~7
2double-1.7E-3081.7E+30815~16
3long double-1.2E-4932~1.2E+493218~19

注意:浮点类型没有无符号unsigned类型。

  • 运算中的精度问题

(1)精度为f:则按照正常的数学结果;
(2)

运行下面程序,分析执行结果:

(1)完整代码见00401——test.c

  #include <stdio.h>
    
    int main(){
       float a = 10.2;  
       float b = 9;  
       float c = a - b;
       printf("%f - %f = %f\n", a,b,c); //(1)精度为f:则按照正常的数学结果;(1.20) 
       return 0;
    }

上面结果看似正确,把程序改成如下:

(2)完整代码见00402——test.c
注意:浮点数必须用精度比较是否相等;

  #include <stdio.h>
    
    int main(){
       float a = 10.2;  
       float b = 9;  
       float c = a - b;
       if(c == 1.2){
           printf("%f == 1.2",c);
       }else{
           printf("%f != 1.2",c);
       }
       return 0;
    }
    

以7位有效数组打印运算结果。

(2)完整代码见00403——test.c
注意:浮点数必须用精度比较是否相等;(计算过程惠会转化为对应的浮点数相加减,所以必须要有精度的统一+结果按照精度比较)

 #include <stdio.h>
    
    int main(){
       float a = 10.2;  
       float b = 9;  
       float c = a - b;
       printf("%.7f - %.7f = %.7f\n", a,b,c);  //10.1999998 - 9.0000000 = 1.1999998
       return 0;
    }

发现运算中存在精度缺失。
如何比较浮点数?使用最小误差。
完整代码见00404——test.c

#include <stdio.h>
    
int main(){
   float a = 10.2;  
   float b = 9;  
   float c = a - b;
   if(fabs(c - 1.2) < 0.000001){
       printf("%f == 1.2\n",c);
   }else{
       printf("%f != 1.2\n",c);
   }
    
   return 0;
}

在误差范围内认为相等。即绝对值差小于精度最小值。float浮点数误差通常为10^(-6)(6位有效数字)。double浮点数误差通常为10^(-15)(15位有效数字)。

3.3 浮点类型选择

浮点类型有三种,通常遵循下面的使用规则:

  1. 大多数情况下使用double
  2. 尽量不要使用float
  3. 过程运算可以使用long double

问题

  • 既然浮点数这么不准确,为什么还需要?
    浮点数通过损失精度,获取更大的表示范围。
  • 试一试:整数除以零会有什么结果
#include <stdio.h>

int main(){
    printf("1/0  = %d\n",1/0);
    return 0;
}

4. 字符类型

字符类型是一个特殊类型,是整型的一种。使用单引号表示字符字面量,例如:字母'a'、数字'1'、空字符''、转义字符\n
通常使用%c作为格式化占位符输入输出,有时也可以使用%d输出字符对应ASCII编码。

  • 打印字符
   #include <stdio.h>
    
    int main(){
        char n='1';
        printf("%c\n%d\n",c,c);
        return 0;
    }
    

4.1 ASCII编码

ASCII编码使用7 位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母,数字0 到9、标点符号, 以及在美式英语中使用的特殊控制字符。

ASCII表的特点:

  1. 字母在ASCII表中是顺序排列的。
  2. 大写字母和小写字母是分开排列的。

C语言中字符即数字。

printf("%d\n",'a');
printf("%c\n",97);

4.2 运算

  1. 字符类型可以像整型一样参与运算。
    例如:
#include <stdio.h>

int main(){
    char a='a';
    printf("%c\n%c\n",a,a+1);
    return 0;
}

字符类型操作含义:

  • 一个字符加上一个数字得到ASCII表中对应新字符。
  • 两个字符相减,得到这两个字符在表中的距离。

实例:

  1. 字符的相关运算;

(1)字符的阿斯克吗值;

char n = '1';
	printf("%c\n%d\n",n,n);
	printf("a=%d\n",'a');
	printf("97=%c\n",97);

(2)字符的运算

char a='a';
	printf("a=%c\n",a);
	printf("a+1=%c\n",a+1);
	printf("a=%d b=%d\n",'a','b');

完整代码见00501——char.c

#include <stdio.h>

int main(){
	/*
	char n = '1';
	printf("%c\n%d\n",n,n);
	printf("a=%d\n",'a');
	printf("97=%c\n",97);
	*/     //(1)字符的阿斯克吗值



	char a='a';
	printf("a=%c\n",a);
	printf("a+1=%c\n",a+1);
	printf("a=%d b=%d\n",'a','b'); //>(2)字符的运算
	
	return 0;
	}
  1. 分别打印出26个大写字母和小写字母。

完整代码见00502——char.c

#include <stdio.h>
int main(){
   char a = 'A';
   char b = 'a'; 
	int i;
	for(i=0;i<26;++i){
		printf("%c",a+i);
	}
	printf("\n");
	for(i=0;i<26;++i){
		printf("%c",b+i);
	}
	printf("\n");
	return 0;
	}
  1. 把一个字符串整型数字转化成整型数字。例如:"1234"转发成1234

完整代码见00503——char.c

#include <stdio.h>

int main(){
	//printf("0=%d\n",'0');
	//printf("1=%d\n",'1');
	
	//char n;
	//n - '0';
	char s[]="1234";
	int n = 0;
	for(i=0;'\0' != s[i];i++){
		n = n*10+(s[i]-'0');
		//printf("%d",s[i]-'0');
	}
	printf("%d\n",n);
}
  1. 判断一个字符串是否存在满足标识符命名规则。
#include <stdio.h>

int main(){
	printf("\033[42;31m张三:\'abc\'\033[0m");
	printf("\r李四\n");
	char name[216];
	scanf("%s",name);
	int i;
	for(i=0;'\0' != name[i];++i){
		char c = name[i];
		
		if( '0'<=c && c<='9'// 数字
		 || 'A'<=c && c<='Z'// 大写字母
	 	 || 'a'<=c && c<='z'// 小写字母
	 	 || c == '_'		// _
					){

		}else{
			printf("%s不是合法标示符\n");
			return;
		}
		
		if('A' <= name[i] && name[i] <= 'Z'){
			name[i] = name[i]-'A'+'a';
		}else if('a' <= name[i] && name[i] <= 'z'){
			name[i] = name[i]-'a'+'A';
		}
	}
	printf("%s\n",name);

	printf("%s是合法标示符\n");
}
  1. 大小写转换

± 32(a-A =32)

4.3 转义字符/逃逸字符

在ASCII表中,除了常见的字符(如:大小写字母、数字等),还包含一些无法打印出来的控制字符或特殊字符。这些字符以反斜线\开头,后面接着一个字符,这种字符被称作转义字符/逃逸字符。

  • 常用的转义字符/逃逸字符
字符含义字符含义
\'单引号\"双引号
\r回车\n换行
\b退格符\f翻页符
\t表格符\\反斜线符

5. 布尔类型

在C99中新增bool类型表示逻辑值,它只有两种值(truefalse)。使用前需要加上头文件stdbool.h


6. 数据转换

6.1 自动类型转换

当运算符左右两边操作数的类型不一致时,会自动转换成较大类型。

  • 整型:charshortintlonglong long
  • 浮点型:intfloatdoublelong double

6.2 强制类型转换

当把一个较大的类型转换成较小的类型,需要强制转换。

强制转换语法

(转换后的类型)

例如:

 printf("%d\n",(int)3.14);

有时,整型转浮点型也需要强制转换。
例如:

 printf("%f\n",(double)1/2);

其中,浮点数转整数采用的是截断方式。

7. 类型变种写法

在C语言中,除了有无符号关键字unsigned,还对应有一个有符号关键字signed,只是通常省略不写。此外,除了char,其他整型类型后面可以加上关键字int表示整型,通常也是省略不写。下面是各种类型其他对应写法。

No.类型其他写法
1charsigned char
2shortsigned short intsigned shortshort int
3intsigned int
4longsigned long intlong intsigned long
5long longsigned long long intsigned long longlong long int

通常也使用unsigned表示unsigned int的简写。

8. 数值常量表示

如何表示天文数字?

直径年龄
地球6371千米45.5亿年
太阳1.392×106千米45.7亿年
银河系10万光年80亿年
宇宙1600亿光年138.2亿年

注:1光年 = 9.46×1012千米

试一下

int earth_diameter = 6371;
int earth_age = 4550000000;
int sun_diameter = 1392000;
int sun_age = 4570000000;
int light_year = 9460000000000;
int galaxy_diameter = 100000*light_year ;
int galaxy_age = 8000000000;
int universe_diameter = 1600000000000*light_year;
int universe_age = 138200000000;
printf("earth_diameter = %d\n",earth_diameter);
printf("earth_age  = %d\n",earth_age);
printf("sun_diameter = %d\n",sun_diameter);
printf("sun_age  = %d\n",sun_age );
printf("galaxy_diameter = %d\n",galaxy_diameter);
printf("galaxy_age = %d\n",galaxy_age);
printf("universe_diameter = %d\n",universe_diameter);
printf("universe_age = %d\n",universe_age);

没有后缀的整数常量默认为int,只能表示21亿左右的数值,如果超过就会警告,执行就会出错,因为int无法表示超出的数字。

  1. 整数常量后缀
No.类型后缀
1L/llong
2LL/lllong long
3U/uunsigned
4L/lU/u组合unsigned long
5LL/llU/u组合unsigned long long
int earth_diameter = 6371;
long long earth_age = 4550000000LL;
int sun_diameter = 1392000;
long long sun_age = 4570000000LL;
long long light_year = 9460000000000LL;
long long galaxy_diameter = 100000*light_year ;
long long galaxy_age = 8000000000LL;
long long universe_diameter = 1600000000000LL*light_year;
long long universe_age = 138200000000LL;
printf("earth_diameter = %d\n",earth_diameter);
printf("earth_age  = %lld\n",earth_age);
printf("sun_diameter = %d\n",sun_diameter);
printf("sun_age  = %lld\n",sun_age );
printf("galaxy_diameter = %lld\n",galaxy_diameter);
printf("galaxy_age = %lld\n",galaxy_age);
printf("universe_diameter = %lld\n",universe_diameter);
printf("universe_age = %lld\n",universe_age);
  1. 浮点数常量后缀
No.类型后缀
1F/ffloat
2F/flong double

没有后缀的浮点数默认为double

  1. 科学记数法
    表示方式:尾数部分e指数部分或者尾数部分E指数部分
    使用科学计数法表示数字更加简单。
  int earth_diameter = 6371;
    long long earth_age = 4.55e9;
    int sun_diameter = 1.392e6;
    long long sun_age = 4.57e9;
    long long light_year = 9.46e12;
    long long galaxy_diameter = 1e5*light_year ;
    long long galaxy_age = 8e9;
    long long universe_diameter = 1.6e12*light_year;
    long long universe_age = 1.382e11;
    printf("earth_diameter = %d\n",earth_diameter);
    printf("earth_age  = %lld\n",earth_age);
    printf("sun_diameter = %d\n",sun_diameter);
    printf("sun_age  = %lld\n",sun_age );
    printf("galaxy_diameter = %lld\n",galaxy_diameter);
    printf("galaxy_age = %lld\n",galaxy_age);
    printf("universe_diameter = %lld\n",universe_diameter);
    printf("universe_age = %lld\n",universe_age);

注意:universe_diameter出现负值。表示long long也装不下这个数字(约为1026大于1012),可以使用double类型表示。

 double universe_diameter = 1.6e12*light_year;
    printf("universe_diameter = %f\n",universe_diameter);

输出数据不容易阅读,可以使用%e%E以科学记数法输出浮点数(注意:%e%E不能用来输出整数)。

 printf("universe_diameter = %e\n",universe_diameter);

科学计数法法除了可以表示极大数,也可以表示极小数,比如电子的直径10-15m.

 double electron_diameter = 10e-15;

9. 逗号表达式

逗号用来连接两个表达式,并以右边的表达式的值为结果。

  表达式1,表达式2,表达式3...... ,表达式n
  • 优先级:所有运算符中最低的
  • 结合律:只左向右
  • 示例
int n = (1+2,2*3,4-5,5/6,6%7);

这里因为逗号运算符优先级最低,所以加上括号运算符。
逗号运算符主要用在for循环。

  • 练习
  1. 数组连接:把两个数组拼接到第三个数组中。
 int a[] = {0,1,2,3,4,5,6,7,8,9};
    int b[] = {10,11,12,13,14,15,16,17,18,19};
    int res[20];
    int j=0;
    for(int i=0;i<10;i++,j++){
        res[j] = a[i];
    }
    for(int i=0;i<10;i++,j++){
        res[j] = b[i];
    }
    for(int i=0;i<20;i++){
        printf("%d\n",res[i]);
    }
  1. 试分析和判断下面代码
 int x,y,z;
    x=1;
    y=1;
    z=x++,y++,++y;
    printf("%d,%d,%d\n",x,y,z);
    

10. 短路与&&、短路或||

  • 说明
    短路与&&:左边表达式是false,右边就不执行,逻辑表达式值为false
    短路或||:左边表达式是true,右边就不执行,逻辑表达式值为true

  • 示例

int x = 1;
printf("%d\n",1<0 && ++x);
printf("x=%d\n",x);
int x = 1;
    printf("%d\n",1>0 || ++x);
    printf("x=%d\n",x);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值