CPU,操作系统位数与地址总线,数据总线

  1. 关于寻址空间

对于32位的windows操作系统,其逻辑地址编码采用的地址位数是32位的,那么操作系统所提供的逻辑地址寻址范围是4GB,而在intel x86架构下,采用的是内存映射技术(Memory-Mapped I/O, MMIO),也就说将4GB逻辑地址中一部分要划分出来与BIOS ROM、CPU寄存器、I/O设备这些部件的物理地址进行映射,那么逻辑地址中能够与内存条的物理地址进行映射的空间肯定没有4GB了,看下面这幅图就明白了:

  1. 1

image.png

  1. 对于64位的操作系统,其逻辑地址编码采用的地址位数是40位,能够最大支持1T的逻辑地址空间。考虑一种情况,假如CPU是64位的,地址总线位数是40位,操作系统也是64位的,逻辑地址编码采用的地址位数也是40位,内存条大小是64GB,那么是不是内存条的64GB全部都能被利用了呢?答案是不一定,因为这里面还要考虑一个因素就是内存控制器,内存控制器位于北桥之内(现在基本都是放在CPU里面了),内存控制器的实际连接内存的地址线决定了可以支持的内存容量,也就是说内存控制器与内存槽实际连接的地址线如果没有40位的话,是无法完全利用64GB的内存条的存储空间的。

引入EOF

如何打开?

image.png

image.png

什么是EOF?

EOF = 1, 表示程序运行异常,错误码只有一位,转换为字符则可读性增强,程序员更加容易判断程序出错

如何触发?

行首输入 Ctrl + Z, 连续输入三次即可退出

image.png

code

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main() {
  5. int i;
  6. while (scanf("%d", &i) != EOF) { /* while 实现循环,后面要有一个小括号 */
  7. printf("i = %d\n", i);
  8. }
  9. return 0;
  10. }

循环获取输入代码存在的问题及解决方案

  1. 成功读取指定数据类型的数据,scanf的返回值是1
  2. 若读取失败,那么返回值是0,仍然不等于负一;
  3. 读取失败指的是 scanf() 希望读取到数字,实际输入为字符;
  4. 那么程序就会陷入死循环,此时应该使用内存刷新代码;
  5. code1 ```c

    define _CRT_SECURE_NO_WARNINGS

    include

    include

int main() { int i, ret; / scanf()成功捕获输入后,其值为1 / while ((ret = scanf(“%d”, &i)) != EOF) { / while 实现循环,后面要有一个小括号 / printf(“i = %d\n”, i); } return 0; }

  1. 6. code2
  2. ```c
  3. #define _CRT_SECURE_NO_WARNINGS
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. int main() {
  7. //vs 2012 使用 fflush(stdin), vs2017 vs2019 使用rewind(stdin)
  8. int i, ret;
  9. /* scanf()成功捕获输入后,其值为1 */
  10. while (rewind(stdin), (ret = scanf("%d", &i)) != EOF) { /* while 实现循环,后面要有一个小括号 */
  11. printf("i = %d\n", i);
  12. }
  13. return 0;
  14. }

为什么不能使用 rewind(stdin)?循环读取字符

原本我们输入多个字符,scanf会依次读取,回车后返回所有字符的转换;
若加入 rewind(stdin),则将清除 除了第一个字符以外的其他字符;

code1

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main() {
  5. char c;
  6. while (scanf("%c", &c) != EOF) {
  7. if (c != "\n") {
  8. printf("%c\n", c - 32); /* 小写转换为大写 */
  9. }
  10. else {
  11. }
  12. }
  13. return 0;
  14. }

image.png

code2

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main() {
  5. char c;
  6. int ret;
  7. while (rewind(stdin), (ret = scanf("%c", &c)) != EOF) {
  8. if (c != "\n") {
  9. printf("%c\n", c - 32); /* 小写转换为大写 */
  10. }
  11. else {
  12. }
  13. }
  14. return 0;
  15. }

image.png

scanf()获取混合输入

%d %f获取输入时都会主动忽视空格,而%c不会,因此会导致以下的错误:

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main() {
  5. int i, ret;
  6. char c;
  7. float f;
  8. ret = scanf("%d%c%f", &i, &c, &f);
  9. printf("i = %d c = %c f= %f", i, c, f);
  10. return 0;
  11. }

image.png

解决方案:在scanf()获取约束前,使用空格预先占用输入时键入的空格

code

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main() {
  5. int i, ret;
  6. char c;
  7. float f;
  8. ret = scanf("%d %c%f", &i, &c, &f);
  9. printf("i = %d c = %c f= %f", i, c, f);
  10. return 0;
  11. }

image.png

printf()的使用

code

  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main() {
  5. printf("name = %s, age = %3d, sex = %c, score= %4.1f", "Caesar", 34, "m", 98.5);
  6. return 0;
  7. }

image.png