zoukankan      html  css  js  c++  java
  • 读书笔记之:C与指针

    第2章 基本概念
    1. 程序的执行过程
    经历几个阶段:首先是载入到内存中。在宿主环境中(具有操作系统的环境),这个任务由操作系统完成。那些不是存储在堆栈中的尚未初始化的变量将在这个时候得到初始值。在独立的环境中,程序的载入必须由手工安排,也可能是通过把可执行代码置入只读内存(ROM)中来完成。
    然后程序执行便开始。在宿主环境中,通常一个小型的启动程序与程序链接在一起,它负责处理一系列日常事务,如收集命令行参数以便使程序能够访问它们。接着,便调用main函数。
    现在,便开始执行程序代码。在绝大多数机器中,程序将使用一个运行时堆栈(stack),它用于存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程中将一直保留他们的值。
    程序执行的最后一个阶段是程序的终止,它可以由多种不同的原因引起。“正常”终止就是main函数的返回。有些执行环境允许程序返回一个代码,提示程序为什么停止执行。在宿主环境中,启动程序将再次取得控制权,并可能执行各种不同的日常任务,如关闭那些程序可能使用过但是并未显示关闭的任何文件。此外,程序也可能是由于用户按下break键或者电话连接的挂起而终止,另外也可能是由于在执行过程中出现错误而自行中断。
    2. 回车换行
    【回车和换行的历史】
    在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行,需要回车换行,此过程,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
    于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。
    【关于回车和换行的更详细的解释】
    首先,打字机打完一行,意味着,从左到右把一行的字打完了,此时打印机的打印头处于最右边,所以,想要继续打字,需要(1)将把打印头移动到最左边,然后(2)打字所用的纸张,换到下一行。
    而(1)打印头移动到最左边的动作,称之为回车;
    (2)打字所用的纸张换到下一行,称之为换行。其是通过打字机的滚筒滚动,将纸向前滚动,就相当于打印头换了一行,处在新一行的最左边的开始的位置了,即所谓的走纸。
    这就是“回车” 和“换行”的来历,从它们的英语名字上也可以看出一二。
    对应到计算机系统中:
    回车:将当前光标移动到同一行中的最左边(假设是从左到右的输入方式)
    换行:保持当前光标的水平位置位置不变,换到下一行。
    因此,将回车和换行联合起来,才是我们所常理解的含义:
    输入完一行后,回车换行到下一行,即光标不仅仅是回到了最左边,而且也换到了下一行。
    【不同系统中表示回车换行含义所用字符不同】
    后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。
    不同的系统里面,对于同样一个”回车换行”的含义,所用的字符不同:

    系统类型       回车换行所用字符
    Linux/Unix     \n=newline=0x0A=10=LF(Line Feed)=换行=Ctrl + J
    Windows/Dos    \r\n=0x0D 0x0A=CR LF=回车 换行
    Mac           \r==return=0x0D=13=CR(Carriage Return)=回车=Ctrl + M
    提示:
    (1).对应的,在Linux中通过键盘输入Enter回车键,输入的是\n=0x0A, 而Windows中的Enter键则是输入的是0x0D 0x0A。
    (2).其中关于0x0A对应的着Ctrl + J,0x0D对应着Ctrl + M等等相关的ASCII的控制字符及输入方式

    第3章 数据类型
    1. 存储类型
     有三个地方可以存储变量:普通内存,运行时堆栈,硬件寄存器
    变量的缺省存储类型取决于它的声明位置。
    (1)在任何代码块之外声明的变量总是存储在静态存储区中,这类是静态变量。这类变量在程序运行之前就已经创建,在程序整个执行期间是始终存在的。
    (2)在代码内部声明的变量缺省是自动存储的,它存于堆栈中,称为自动变量。这些变量是在程序执行到该代码块的时候,被自动的创建,当程序离开该代码块的时候,被自动销毁。
    (3)如果在自动变量前面加上static,那么它的存储类型就从自动变为了静态,所以它也会在程序运行之前就创建,在该变量所在代码块的代码第一次执行的时候,该变量被初始化,下次再次执行时,不再对其初始化,而是继续使用之前的值。但是注意,它的作用域还是块作用域 的。
     函数的形式参数不能声明为静态static,因为实参总是在堆栈中传递给参数,用于支持递归。
    2. 初始化
    自动变量和静态变量的初始化存在一个重要的差别。在静态变量的初始化中,我们可以把可执行程序文件想要初始化的值放在当程序执行时变量将会使用的位置。当可执行文件载入到内存时,这个已经保存了正确初始值的位置将赋值给那个变量。完成这个任务并不需要额外的时间,也不需要额外的指令,变量将会得到正确的值。如果不显式地指定初始值,静态变量将初始化为0
    自动变量的初始化将需要更多的开销,因为当程序链接时还无法判断自动变量的存储位置。事实上,函数的局部变量在函数的每次调用中都可能占据不同的位置。基于这个理由,自动变量没有缺省的初始值,而显示的初始化将在代码块的起始处插入一条隐式的赋值语句。
    这样的话造成了:
    (1)自动变量的初始化较之赋值语句效率并无提高,出了声明为const的变量之外,在声明变量的同时进行初始化和先声明后负责只有风格之差,并无效率之别。
    (2)每次执行到所在的代码块时都重新初始化,这一点与静态变量不同。
    3. static 修饰符
      对作用域无影响,随作用域的不同而产生不同的效果
     (1)用于函数定义或代码块之外的变量声明时,static关键字修改标识符的链接属性,从外部链接变为内部链接,但存储类型和作用域不受影响。
     (2)用于代码块内部的变量时,改变变量的存储类型,从自动变量改为静态变量,不改变链接属性和作用域。
    如果一个变量声明于代码块的内部,在它前面添加extern将使他引用的是全局变量而非局部变量。
    具有external链接属性的实体总是具有静态存储类型。


    第15章 输入输出
    1. 字符I/O宏,
    fgetc和fputc都是真正的函数,但是getc、putc、getchar和putchar都是通过#define指令定义的宏。
    宏在执行时间上效率较高,而函数在程序的长度方面更胜一筹,之所以提供两种类型的方法,是为了允许你根据程序的长度和执行速度哪个更重要选择正确的方法。
  • 相关阅读:
    【模板】常系数线性递推
    【模板】多项式除法
    【模板】多项式求逆
    codeblock的一个小问题
    IP分片浅析
    [LeetCode] Excel Sheet Column Number
    [LeetCode] Excel Sheet Column Title
    [LeetCode] Maximum Gap
    编程计算并输出1~n之间所有素数之和
    [LeetCode] Compare Version Numbers
  • 原文地址:https://www.cnblogs.com/xkfz007/p/2369150.html
Copyright © 2011-2022 走看看