zoukankan      html  css  js  c++  java
  • C和指针笔记-第3章 数据

    这是我读《C和指针》第3章做的笔记,主要内容是C语言中数据的类型、不同类型的特点和使用以及变量的三个属性--作用域、链接属性和存储类型,希望能对你有所帮助

    • 基本数据类型

    在C语言中,仅有4种基本数据类型:整型、浮点型、指针和聚合类型(如数组和结构等)。

    • 整型:字符、短整型、整型和长整型(都有singed和unsigned(有无符号)之分)。

    长整型至少应该和整型一样长,而整型至少应该和短整型一样长。标准并没有规定长整型必须比短整型长,只是规定它不得比短整型短。ANSI标准加入了一个规范,说明了各种整型值的最小允许范围:short int至少16位,long int至少32位。(至于缺省的int究竟是16位还是32位,或者是其他值则由编译器设计者决定。通常这个选择的缺省值是这种机器最为自然(高效)的位数。)

    尽管设计char类型变量的目的是为了让它们容纳字符型值,但字符在本质上是小整型值。缺省的char要么是signed char,要么是unsigned char,这取决于编译器。这个事实意味着不同机器上的char可能拥有不同范围的值。所以,只有当程序所使用的char型变量的值位于signed char和unsigned char的交集中,这个程序才是可移植的。例如,ASCII字符集中的字符都是位于这个范围之内的。    

    当可移植问题比较重要时,字符是否为有符号数就会带来两难的境地。最佳妥协方案就是把存储于char型变量的值限制在signed char和unsigned char的交集内,这可以获得最大程度的可移植性,同时又不牺牲效率。并且,只有当char型变量显式声明为signed或unsigned时,才对它执行算术运算。

    字面值(literal)这个术语是字面值常量的缩写——这是一种实体,指定了自身的值,并且不允许发生改变。ANSI C允许命名常量(声明为const的变量)的创建,它与普通变量极为类似。区别在于,当它被初始化以后,它的值便不能改变。

    • 十进制整型字面值可能是int,long或unsigned long。在缺省情况下,它是最短类型但能完整容纳这个值。
    • 整数也可以用八进制来表示,只要在数值前面以0开头。整数也可以用十六进制来表示,它以0x开头。
    • 另外还有字符常量。它们的类型总是int。你不能在它们后面添加unsigned或long后缀。字符常量就是一个用单引号包围起来的单个字符(或字符转义序列或三字母词),诸如:

    枚举(enumerated)类型就是指它的值为符号常量而不是字面值的类型

    • 以下面这种形式声明:
      enum Jar_Type(CUP,PINT,QUART,HALF GALLON,GALLON};//这条语句声明了一个类型,称为Jar Type。
    • 这种类型的变量按下列方式声明:
      enum Jar_Type A,B,C;
    • 如果某种特别的枚举类型的变量只使用一个声明,你可以把上面两条语句组合成下面的样子:
      enum { CUP,PINT,QUART,HALF GALLON,GALLON} A,B,C;
    • 这种类型的变量实际上以整型的方式存储,这些符号名的实际值都是整型值。这里CUP是0,PINT是1,以此类推。

    • 适当的时候,你可以为这些符号名指定特定的整型值,如下所示:

      enum Jar_Type {CUP = 8,PINT = 16,QUART=32,HALF GAILON = 64,GALLON = 128};
    • 只对部分符号名用这种方式进行赋值也是合法的。如果某个符号名未显式指定一个值,那么它的值就比前面一个符号名的值大1

    • 浮点型:float、double、long double类型

    ANSI标准仅仅规定long double至少和double一样长,而double至少和float一样长。

    标准同时规定了一个最小范围:所有浮点类型至少能够容纳从10-37到1037之间的任何值。

    浮点数字面值在缺省情况下都是double类型的,除非它的后面跟一个L或l表示它是一个long double类型的值,或者跟一个F或f表示它是一个float类型的值。

    • 指针

    在程序中使用字符串常量会生成一个“指向字符的常量指针”。当一个字符串常量出现于一个表达式中时,表达式所使用的值就是这些字符所存储的地址,而不是这些字符本身。因此,你可以把字符串常量赋值给一个“指向字符的指针”,后者指向这些字符所存储的地址。但是,你不能把字符串常量赋值给一个字符数组,因为字符串常量的直接值是一个指针,而不是这些字符本身。

    如果你需要修改字符串,请把它存储于数组中,因为对一个常量进行修改可能殃及程序中其他字符串常量。

    • 基本声明

    在声明整型变量时,如果声明中已经至少有了一个其他的说明符,关键字int可以省略。因此,这两个声明的效果是相等的:unsigned short int a;unsigned short a;

    signed 关键字一般只用于char类型,因为其他整型类型在缺省情况下都是有符号数。至于char是否是signed,则因编译器而异。所以,char可能等同于signed char,也可能等同于unsigned char。

    浮点类型除了long double之外,其余几个说明符(short,signed,unsigned)都是不可用的。

    声明指针:(最好把*写在靠近名字的一侧:*a产生的结果是int类型)

    int *a; //a 是一个指向int的指针

     声明指针变量时也可设定初始值:

    char *message="Hello world!"//这条语句把message声明为一个指向字符的指针,并用字符串常量中第1个字符的地址对该指针进行初始化。

    看上去初始值似乎是赋给表达式*message,事实上它是赋给message本身(指针本身而不是指针所指向的值)的,等同于:

    char *message;
    message="Hello world!"

    隐式声明:省略类型名的声明,函数如果不显式地声明返回值的类型,它就默认返回整型,不建议使用隐式声明。

    • typedef

    typedef机制允许你为各种数据类型定义新名字。typedef声明的写法和普通的声明基本相同,只是把typedef这个关键字出现在声明的前面:

    typedef unsigned char u8;

    使用typedef 声明类型可以减少使声明变得又臭又长的危险,尤其是那些复杂的声明。

    应该使用typedef而不是#define来创建新的类型名,因为后者无法正确地处理指针类型。

    • 常量

    使用const关键字来声明变量,值无法修改,赋初值方法:

    1. 在声明时初始化
    2. 在函数声明为const的形参在函数被调用时会得到实参的值。

    指针常量和常量指针:

    int *pi//指向int型的指针pi
    
    int const *pci;//常量指针:可以修改指针的值,不能修改指针所指向的值(指向常量的指针)
    
    int * const cpi;//指针常量:指针是常量,不能修改指针的值,可以修改指针所指向的值

    当你声明变量时,如果变量的值不会被修改,你应当在声明中使用const关键字,如果要使用字面值常量的话使用#define更好。

    • 作用域

    标识符的作用域就是程序中该标识符可以被使用的区域:

    1. 其他函数都无法通过这些变量的名字访问它们,因为这些变量在它们的作用域之外便不再有效。
    2. 只要分属不同的作用域,你可以给不同的变量起同一个名字

    编译器可以确认4种不同类型的作用域——文件作用域、函数作用域、代码块作用域和原型作用域。标识符声明的位置决定它的作用域。

    代码块作用域:

    位于一对花括号之间的所有语句称为一个代码块,当代码块嵌套时,如果内层代码块有一个标识符的名字与外层代码块的一个标识符同名,内层的那个标识符就将隐藏外层的标识符——外层的那个标识符无法在内层代码块中通过名字访问。

    在K&R C中,函数形参的作用域开始于形参的声明处,位于函数体之外。如果在函数体内部声明了名字与形参相同的局部变量,它们就将隐藏形参。这样一来,形参便无法被函数的任何部分访问。

    文件作用域:

    任何在所有代码块之外声明的标识符都具有文件作用域,它表示这些标识符从它们的声明之处直到它所在的源文件结尾处都是可以访问的。

    原型作用域:

    只适用于在函数原型中声明的参数名,在原型中(与函数的定义不同),参数的名字并非必需。

    函数作用域:

    基本上,函数作用域可以简化为一条规则——一个函数中的所有语句标签必须唯一。

    • 链接属性:external(外部)、internal(内部)和none(无)

    标识符的链接属性(linkage)决定如何处理在不同文件中出现的标识符。标识符的作用域与它的链接属性有关,但这两个属性并不相同。
    链接属性一共有3种:external(外部)、internal(内部)和none(无)。

    没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的实体。

    属于internal链接属性的标识符在同一个源文件内的所有声明中都指同一个实体,但位于不同源文件的多个声明则分属不同的实体。

    属于external链接属性的标识符不论声明多少次、位于几个源文件都表示同一个实体。

    缺省状态下的链接属性:

    关键字extern和static用于在声明中修改标识符的链接属性:

    static只对缺省链接属性为external的声明才有改变链接属性的效果。

    如果某个声明在正常情况下具有external链接属性,在它前面加上static关键字可以使它的链接属性变为internal,例如,如果第2个声明像下面这样书写:static int b;那么变量b就将为这个源文件所私有。在其他源文件中,如果也链接到一个叫做b的变量,那么它所引用的是另一个不同的变量。类似,你也可以把函数声明为static,如:static int c(int d)可以防止它被其他源文件调用。

    extern关键字的规则更为复杂。一般而言,它为一个标识符指定external链接属性,这样就可以访问在其他任何位置定义的这个实体。

    • 存储类型

    有三个地方可以用于存储变量:普通内存、运行时堆栈、硬件寄存器。

    变量的缺省存储类型取决于它的声明位置。

    普通内存:凡是在任何代码块之外声明的变量总是存储于静态内存中,也就是不属于堆栈的内存,这类变量称为静态(static)变量。对于这类变量,你无法为它们指定其他存储类型。静态变量在程序运行之前创建,在程序的整个执行期间始终存在。它始终保持原先的值,除非给它赋一个不同的值或者程序结束。

    运行时堆栈:在代码块内部声明的变量的缺省存储类型是自动的(automatic),也就是说它存储于堆栈中,称为自动(auto)变量。有一个关键字auto就是用于修饰这种存储类型的,但它极少使用,因为代码块中的变量在缺省情况下就是自动变量。在程序执行到声明自动变量的代码块时,自动变量才被创建,当程序的执行流离开该代码块时,这些自动变量便自行销毁。

    对于在代码块内部声明的变量,如果给它加上关键字static,可以使它的存储类型从自动变为静态。具有静态存储类型的变量在整个程序执行过程中一直存在,而不仅仅在声明它的代码块的执行时存在。注意,修改变量的存储类型并不表示修改该变量的作用域,它仍然只能在该代码块内部按名字访问。函数的形式参数不能声明为静态,因为实参总是在堆栈中传递给函数,用于支持递归。

    寄存器:关键字register可以用于自动变量的声明,提示它们应该存储于机器的硬件寄存器而不是内存中,这类变量称为寄存器变量。通常,寄存器变量比存储于内存的变量访问起来效率更高。但是,编译器并不一定要理睬register关键字,如果有太多的变量被声明为register,它只选取前几个实际存储于寄存器中,其余的就按普通自动变量处理。

    在典型情况下,你希望把使用频率最高的那些变量声明为寄存器变量。在有些计算机中,如果把指针声明为寄存器变量,程序的效率将能得到提高,尤其是那些频繁执行间接访问操作的指针。

    • static关键字

    当它用于函数定义时,或用于代码块之外的变量声明时:static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响。用这种方式声明的函数或变量只能在声明它们的源文件中访问。

    当它用于代码块内部的变量声明时:static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行之前创建,当函数每次被调用时,它并不会被重新初始化,并且在程序的整个执行期间一直存在,而不是每次在代码块开始执行时创建,在代码块执行完毕后销毁。

    参考:C和指针(第二版) 美〕Kenneth A.Reek著  徐波译   人民邮电出版社

  • 相关阅读:
    Airodump-ng——Description
    kali 2.0 — WIFI——commands
    国外整理的一套在线渗透测试资源合集
    A collection of android security related resources.
    cBPM
    cBPM-android
    CentOS7 安装 gcc-4.9.0
    install Android Studio 1.3 —— VM Acceleration on Linux
    08嵌入式—蔺小会—初创公司需要怎样的管理模式?
    Nodejs开发框架Express4.x开发手记
  • 原文地址:https://www.cnblogs.com/XIEjm/p/12894240.html
Copyright © 2011-2022 走看看