这里c语言的强制类型转换,大小端的问题在之前C语言中都提过了。
这里之前提过的边界对齐在补一点东西。
现代计算机通常是按字节编址,即每个字节对应一个地址;通常也支持按字、按半字、按字节寻址; 之前提过,字和字节的不同,1 字节是8bit,而 一个字 和存储字长有关,若存储字长为32位,则1个字为 32bit。这里为什么采用边界对齐的方式存储在C语言中结构体的那一部分也已经提过,为了方便读取,以空间换时间的方式。
这里还有一个将按字寻址和按半字寻址转换成按字节寻址的方法,前置逻辑左移两位,后者逻辑左移一位即可。
存储系统的基本概念:
存储器的层次化结构:
外存(磁带,光盘)-> 辅存 (磁盘)-> 内存(主存)-> 高速缓冲存储器(cache)-> cpu
从前到后(前 -> 后),运算速度越来越快,容量越来越小,价格越来越高;
辅存中的数据只有调入主存后,才能被CPU访问,主存和cache是可以直接被cpu读写的。
数据在辅存和主存的传输是通过 硬件+操作系统实现的;主存,cache,cpu三者之间数据传输是通过硬件自动完成的。
主存 - 辅存:实现了虚拟存储系统,解决了主存容量不够的问题。
cahce - 主存:解决了主存和cpu速度不匹配的问题。
存储器按存取方式可以分为:
随机存取存储器:
读写任何一个存储单元所需时间都相同,与存储单元所在的物理位置无关。
顺序存取存储器:
读写一个存储单元所需时间取决于存储单元所在的物理位置。
直接存取存储器:
既有随机存取的特性,也有顺序存取特性。直接选取信息所在区域,然后按顺序方式存取。
像顺序存取存储器和直接存取存储器这种读写某一存储单元所需时间与存储单元的物理位置有关的存储器也叫做串行访问存储器。
相联存储器:
可以按内容访问的存储器,可以按内容检索到存储位置进行读写,“快表“就是一种相联存储器。
按信息的可更改性:
读写存储器:(Read/Write Memory)
即可读,也可写;
只读存储器:(Read Only Memory)
只能读,不能写。(实际上很多ROM也可以多次读写,只是比较麻烦)
按信息的可保存性;
断电后,存储信息消失的存储器 -- 易失性存储器(主存,cache)
断电后,存储信息依然保持的存储器 -- 非易失性存储器(磁盘,光盘)
信息读出后,原存储信息被破环 -- 破坏性读出(如DRAM芯片,读出数据后要进行重写)
信息读出后,原存储信息不被破坏 -- 非破坏性读出(如SRAM芯片,磁盘,光盘)
存储器的性能指标:
1、存储容量:存储字数*字长;
2、单位成本:每位价格 = 总成本/总容量 (总容量的单位是bit,位)。
3、存储速度:数据传输率 = 数据的宽度 / 存储周期 (数据的宽度即存储字长)
1)、存取时间:存取时间是指从启动一次存储器操作到完成该操作所经历的时间, 分为读出时间和写入时间。
2)、存期周期:存期周期又称位读写周期或访问周期,它是指存储器进行一次完整的读写操作所需的全部时间(包括存取之后的恢复时间),即连续两次独立的访问存储器操作之间所需要的最小时间间隔。
主存带宽:主存带宽又称为数据传输率,表示每秒从主存进出信息的最大数量,单位为 字/秒,字节/秒 或 位/秒。
主存储器的基本组成:
基本的半导体元件及原理:
像这个MOS管控制着电路是否接通,当电路接通之后,电容就会和数据线的另一端导通,通过电容本身电压的高低 (高电压表示 1 ,低电压表示 0)可以完成数据 1/0 的读取,同时也可以通过数据线对电容充放电完成 1 /0 的写入。(这些都是在 MOS管导通情况下完成的,MOS管相当于电路开关。)
这个每八个半导体元件构成一个存储单元(一个半导体代表一位,也就是一字节),然后每一个地址控制着一字节的大小。之前提过MAR是存储地址寄存器,cpu通过地址总线向MAR传输地址,然后通过译码器就可以根据地址找到对应的字选线,字选线可以控制MOS管是否导通,从而决定半导体和数据总线之间是否导通,决定数据总线是否能够进行读写。
这里还有一个控制电路,在后面会有比较详细的解释。
由于一个内容条中可能包含多块存储芯片,片选线就是决定读取哪一块存储芯片的。
还有一个总容量,总容量和上面说的存储容量应该是一样的,只不过表示有点区别,总容量是存储单元个数*存储字长 ,存储容量是存储字数*字长,存储字数就是可以有多少地址,有多少地址也就可以管多少存储单元,所有两者应该一样。
这个题我最开始是打算引入一个变量来观测a,b是否循环一个周期了,这样虽然能做但还是比较麻烦的,但后面突然意识到可以通过模求余来表示第几次出拳,这样感觉就比较巧,如果a的出拳周期是3 ,那么0,3,6的模3余都是0,都表示第一次,然会 1,4,7都余1表示第二次,这样不用借助变量,而且处理起来也算方便。
#include
int main()
{
int n = 0, a = 0, b = 0;
scanf("%d %d %d", &n, &a, &b);
int* _a = (int*)malloc(sizeof(int) * a);
int* _b = (int*)malloc(sizeof(int) * b);
int i = 0; int suma = 0, sumb = 0; int ja = -1, jb = -1;
for (i = 0; i < a; i++)
{
scanf("%d", &_a[i]);
}
for (i = 0; i < b; i++)
{
scanf("%d", &_b[i]);
ja++;
if ((_b[i] == 5 && _a[ja] == 0) || (_b[i] == 2 && _a[ja] == 5) || (_b[i] == 0 && _a[ja] == 2))
sumb++;
else if ((_b[i] == 0 && _a[ja] == 5) || (_b[i] == 5 && _a[ja] == 2) || (_b[i] == 2 && _a[ja] == 0))
suma++;
if (ja == a - 1) ja = -1;
n--;
}
for (i = 0; i < n; i++)
{
ja++; jb++;
if ((_b[jb] == 5 && _a[ja] == 0) || (_b[jb] == 2 && _a[ja] == 5) || (_b[jb] == 0 && _a[ja] == 2))
sumb++;
else if ((_b[jb] == 0 && _a[ja] == 5) || (_b[jb] == 5 && _a[ja] == 2) || (_b[jb] == 2 && _a[ja] == 0))
suma++;
if (jb == b - 1) jb = -1;
if (ja == a - 1) ja = -1;
}
if (suma > sumb)
printf("A\n");
else if (sumb > suma)
printf("B\n");
else
printf("draw\n");
return 0;
}
这个是用 模求余处理的
#include
int main()
{
int n = 0, a = 0, b = 0;
scanf("%d %d %d", &n, &a, &b);
int* _a = (int*)malloc(sizeof(int) * a);
int* _b = (int*)malloc(sizeof(int) * b);
int i = 0; int suma = 0, sumb = 0;
for (i = 0; i < a; i++)
{
scanf("%d", &_a[i]);
}
for (i = 0; i < b; i++)
{
scanf("%d", &_b[i]);
}
for (i = 0; i < n; i++)
{
if ((_b[i%b] == 5 && _a[i%a] == 0) || (_b[i % b] == 2 && _a[i % a] == 5) || (_b[i % b] == 0 && _a[i % a] == 2))
sumb++;
else if ((_b[i % b] == 0 && _a[i % a] == 5) || (_b[i % b] == 5 && _a[i % a] == 2) || (_b[i % b] == 2 && _a[i % a] == 0))
suma++;
}
if (suma > sumb)
printf("A\n");
else if (sumb > suma)
printf("B\n");
else
printf("draw\n");
return 0;
}
还有个题,错误一直找不到了,今天就不发了。
突然明白了,我是把头对齐运算的,加减应该是把尾对齐。
t