C语言第七章——数据类型

引子:sizeof的用法

  • 是一个运算符,给出某个类型和变量在内存中所占据的字节数
  • sizeof(int) sizeof(i)
  • 是静态运算符,它的结果在编译时刻就已经决定了
  • 不要在sizeof的括号中做运算,这些运算不会做的,即只看结果是什么类型的,不会真的去做计算,比如sizeof(a++)这种事情a不会++,但sizeof(a+1.0)确实是会先把int a转化为double 然后再得出double的大小
  • 注:如何理解上面这一点?
    答:这其实就是,sizeof确实做了计算,得到了结果,但它是在 **”心里“或者”草稿纸“上做的,它并不是需要知道结果,只是在”心里“或者”草稿纸“**知道结果以后,得到括号里的类型就好,然后就把结果扔了,所以相当于对计算机来说,其实没做括号里的运算

C语言的类型

在这里插入图片描述

关于类型有何不同的那张ppt,5个方面要注意的

整数

关于几种整数类型、

在这里插入图片描述

下面是用自己的电脑来看这些数据类型的

#include<stdio.h>
int main()
{
	printf("%ld\n",sizeof(char));
	printf("%ld\n",sizeof(short));
	printf("%ld\n",sizeof(int));
	printf("%ld\n",sizeof(long));
	printf("%ld\n",sizeof(long long));
	
	printf("%ld\n",sizeof(float));
	printf("%ld\n",sizeof(double));
	printf("%ld\n",sizeof(long double));
	return 0;
 } 

我这台电脑的运行结果是
在这里插入图片描述

关于为什么int和long根据计算机和编译器有不同的结果?
如下图,int想要表达的就是一个寄存器的大小,寄存器通过总线一次性可以把这么多的数据给了RAM,所谓“这么多的数据”即一个int,int就是用来表达寄存器的
在这里插入图片描述

计算机内整数是如何表达的

引子:

  • 计算机里一切都是二进制,他是什么取决于我们怎么看待它!!!
  • 所有的类型最终的意义是我们通过什么方式去看待它,而不是表明他是怎么表达的

原码和补码
负数是由补码表示的

以一个字节(8位)举例
0-> 0000 0000
1-> 0000 0001
现在要找到一个数是-1,使得,-1+1=0,即
1111 1111+0000 0001-> 1 0000 0000
而第九位无法表达,因此,其实是255+1->256,然而这里的256因为无法表达第9位,而变成了0,这里的1111 1111本来是255,也就变成了-1

  • 对于-a来说,补码就是0-a,实际上是2n-a,n是这种类型的位数

对应在上面的例子中,对于-1来说,补码就是0000 0000-0000 0001=1111 1111,(0-1=-1)实际上是(1 0000 0000-0000 0001=1111 1111注意有溢出的1)28-1=255

  • 1111 1111被当作纯二进制数的时候是255,被当作补码来说是-1(再次反应的是引子中说的,在于我们怎样看待它)
  • 补码的意义在于拿原码和补码就可以加出一个带溢出的0,进行的运算仍然是纯二进制的运算

整数的范围——关于越界

在这里插入图片描述
如图,正是因为char所表达的范围变成了一个圆,所以才会有

  • 同样是8位,只能表示256个数,但char表示的是则是-27到27-1(即-128~127,即上图中圆的内圈),而unsigned char表示的则是0到28-1(即0~255,即上图中圆的外圈)
  • char中,127+1=-128,127+2=-127
  • unsigned char中,255+1=0,0-2=254

整数的格式化输入输出

只有两种%d %ld 如果表示无符号的则是%u,%lu

  • 所有int和比int小的数都用%d
  • 比int大的都用%ld
  • 说明:其实没什么特别说明的话,整数就用int(输入输出都是%d),浮点数就用double(输入是%lf,输出是%f)就可以

顺便做个拓展,如果写出下面的代码,其实就是想表达全部位都是1的时候用无符号数输出,但会发现输出的数字是一样的,这是为什么???

#include<stdio.h>
int main()
{
	char c=-1;
	int i=-1; 
	printf("%u %u",c,i);
	
	
	return 0;
 }

答案是unsigned int所能表示的最大值
这就非常好理解了,有以下的说明

注意: 这里需要注意的就是,之前提到过的两点

  • int想要表达的就是一个寄存器的大小,寄存器通过总线一次性可以把这么多的数据给了RAM,所谓“这么多的数据”即一个int,int就是用来表达寄存器的就算是char也是一次给RAM一个int的大小
  • 所以为什么所有int和比int小的数都用%d也是这个道理,即int和long表示几个字节是由编译器和计算机决定的,这是很有道理的,超过int大小以后,一次给RAM的是一个long的大小,所以
    1.int和long表示的是和寄存器相关的事情
    2.所有int和比int小的数都用%d,比int大的都用%ld
    这两件事情是同一件事情

字符类型char——既是整数类型也是字符类型

'1’的ASCII码是49
#include<stdio.h>
int main()
{
	char c;
	scanf("%c",&c) ;
	printf("%c %d",c,c);

	return 0;
 }

这里输入:1
输出结果:1 49

#include<stdio.h>
int main()
{
	char c;
	scanf("%d",&c) ;
	printf("%c %d",c,c);

	return 0;
 }

这里输入:49
输出结果:1 49
!!!
便一目了然了

字符的运算

字符也是可以做类似++这种操作的,毕竟是ASCII码的运算

大小写字母转换

常见的ASCII码可以简单知道一下,比如

  • a的ASCII码数值是97,A的ASCII码数值是65。
  • ASCII码值中,大小写字母码的关系是对应的大写字母与小写字母之间相差32
  • 大写字母码<小写字母码

因此我们就很容易的可以得出来大小写字母的转换公式

  • a+‘a’-‘A’ ——把大写字母变成小写字母
  • a+‘A’-‘a’ ——把小写字母变成大写字母
    注意,根本不需要强记,要充分的理解,可以用a的ASCII码数值是97,A的ASCII码数值是65的例子来理解

浮点数

整数是二进制数,是补码形式
浮点数是编码形式

表达范围

这里的表达范围说的很详细

  1. 接近0的很小的一个数到很大的一个数,负数一边也是(这表示其实在接近0的很小的一片区域浮点数是表达不了的)
  2. 0(虽然接近0的小片区域不能表达,但是可以表达0)
  3. ±inf(正负无穷)
  4. nan(不存在)
    这里用一个例子说明±inf和nan
#include<stdio.h>
int main()
{
	
	printf("%f\n",12.0/0.0);
	printf("%f\n",-12.0/0.0);
	printf("%f\n",0.0/0.0);
	return 0;
 }

输出结果:
1.#INF00
-1.#INF00
-1.#IND00

注意:如果是整数printf("%d\n",12/0);其实编译都通不过,但是浮点数中其实定义了0.0可以做分母,专门来这样表示了无穷和不存在的情况
注注意:这里0.0表示的就是0,不能理解成0.0是表示的无限接近0的一个很小的数,所以才能做分母,这样理解是错误的,因为有如下的代码说明0和0.0相等

#include<stdio.h>
int main()
{
	int i=0;
	double k=0.0;
	if(i==k)
	{
		printf("here!");
	}
	return 0;
 }

确确实实输出了here!那就没话说了,而且浮点数的表达范围明确说可以表达0了

浮点数不能被准确表达!!!

但这种判断的方法是可行的,因为浮点运算是有精度的,可以用类似的思路来写代码来说明

#include<stdio.h>
int main()
{
	float a=1.23f;
	float b=2.34f;
	float c=a+b;
	if(c==3.57)
	{
		printf("here!");
	}else
	{
		printf("不相等,c=%.10f,c=%f",c,c);
	}

	return 0;
 }

输出结果是:
不相等,c=3.5699999332,c=3.570000
这里就说明了浮点数不能准确表达,注意这里要在1.23和2.34后面专门加上f来说明是浮点数,而前面的0.0就算加了f,也是和0相等的,当然了,不加f肯定也是浮点数啊,只不过默认是双精度浮点数

  • 带小数点的字面量是double而不是float,float需要用f或F后缀来表明身份
  • 拓展:那既然两个浮点数不能这样子去做相等的运算,那如果真想做两个浮点数相等怎么办呢?
    答:可以这样子,fabs(a-b)<1e-12,即求两个数的差的绝对值,如果小于一个很小的数,比如1e-12或者1e–8这样子,那就说明这两个数是人类意义上的相等,计算机意义上他们肯定还是不相等,就像上面的这个例子一样,当然,如果要用fabs函数肯定要先加载头文件#include<math.h>,因为毕竟求绝对值是数学符号(在本章最后总结了已经遇到的常用的头文件)

关于输出精度的事情

用例子来说明

#include<stdio.h>
int main()
{
	
	printf("%.3f\n",0.0049);
	printf("%.30f\n",0.0049);
	printf("%.3f\n",0.00049);
	return 0;
 }

输出结果:
0.005
0.004899999999999999800000000000
0.000

输出的结果会得出这样几个结论:

  • 由第一个和第三个输出的结果得出,输出精度是会四舍五入的
  • 第二个结果才是计算机内部真实的这个数,因为0.0049计算机没法准确表达——浮点数计算机没法准确表达,因为数学中的数是连续的,而计算机必须用离散的数来表示

类型转换

自动类型转换
  • 当运算符的两边出现不一致的类型时,会自动转换成比较大的类型
  • 对于printf,任何小于int的类型都会被转换成int,float会被转换成double(所以这就是输出double的时候并不需要搞一个%lf 只需要%f,都是有原因的)
  • 对于scanf,要输入short,需要%hd(所以输入double的时候也要%lf)
强制类型转换
(int)10.2;

注意:强制类型转换的优先级高于四则运算,毕竟是单目运算符

逻辑类型(运算)——特殊的整数运算

  • 逻辑类型本身是人为定出来的
  • 逻辑类型是特殊的整数类型,逻辑运算是特殊的整数运算
  • 逻辑运算优先级!高于&&高于||(运算优先级要熟悉,见C语言第一章——基本运算这篇文章有总结)
  • 短路!!!逻辑运算是自左向右进行的,如果左边的结果已经能决定结果了,就不会做右边的运算,这对人来说也是很容易理解的
!a //非
a&&b//与
a||b//或

a>4&&a<6//表示4<a<6
a>'A'&&a<'Z'//判断a是不是大写字母
!age<20//要注意这里是先算非运算,因为是单目运算符

指针

指针会第八章进行单独的讲解

自定义类型

这里留下来的一个问题:

  • 自定义类型指的是结构体吗??

八进制和十六进制

表示八进制,前面加0
表示十六进制,前面加0x

int i=012;
int k=0x12;

注意:八进制和十六进制仅仅是如何把数字表达为字符串,与内部如何表达数字无关(内部表达的数字肯定是二进制啊!)

总结:%的输入输出格式

整数

%d 表明输入输出的是十进制(Decimal)
%o 表明输入输出的是八进制(Octal)
%x %X 表明输入输出的是十六进制(Hexadecimal)(因为有字母,输出大写字母时用%X)
%c 表明输出的是字符
%p 表明输出的是地址

浮点数

%f double类型的输出,float类型的输入和输出
%lf double类型的输入(具体查看自动类型转换的后两个点)
%e %E 表示输入输出的是科学计数法,例子如下

#include<stdio.h>
int main()
{
	
	double i=1234.5678; 
	double k;
	scanf("%e",&k);//输入1e-10 
	printf("%E %e %f\n",i,i,i);
	printf("%E %e %f",k,k,k);
	
	return 0;
 }

计算结果:
1.234568E+003 1.234568e+003 1234.567800
3.884164E-315 3.884164e-315 0.000000
足以说明用法了(最后一个是0是因为他表达的数跑到精度后面了,如果想要看到他表示的数,可以把%f改成%.16f让他输出小数点后16位的就可以了,这倒不是什么大的事情)是输出精度的事情

总结:逃逸字符(转义字符)

\n
\t 制表位,到固定的位置
\b 回退一格
\
*
"

总结:目前为止用到的头文件

#include<stdio.h>  

目前用到的最多的 标准输入输出头文件,原因是里面用到了scanf printf这样的函数

#include<math.h>  

主要是一些数学的函数,比如在本章中浮点数求相等例子中用到的fabs求绝对值函数

#include<time.h>

是一些和时间有关的函数,比如猜数游戏的程序中用到了time(0),即获取当前的时间,这个程序中用这个函数是为了取当前的时间作为不同的数来当作随机种子,例子附在下面

#include<string.h>

与字符串相关的函数,比如strcpy这些对字符串进行操作的函数

#include<stdlib.h> 

mallocfree等对内存的操作函数,以及srand(),rand()函数
srand():种下一个随机种子,括号里的数就是随机种子,数相同,随机种子相同
rand():产生一个随机数

#include <time.h>

int main()
{
	srand(time(0));
	int a = rand();
	
	printf("%d\n", a);
	printf("%d\n", a%100);

	return 0;
} 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值