zoukankan      html  css  js  c++  java
  • 《C程序设计语言》笔记 (六) 结构

    6.1结构的基本知识

    结构是一个或多个变量的集合,这些变量可能为不同的类型,为了处理的方便而将这些变量组织在一个名字之下
    
    结构可以拷贝、赋值、传递给函数,函数也可以返回结构类型的返回值
    
    自动结构和数组现在也可以进行初始化
    
    struct point{
      int x;
      int y;
    }
    
    关键字struct引入结构声明
    
    结构声明由包含在花括号内的一系列声明组成
    
    关键字struct后面的名字是可选的,称为结构标记
    
    结构标记用于为结构命名,在定义结构后,结构标记就代表花括号内的声明,可以用它作为声明的简写形式
    
    结构中定义的变量称为成员
    
    结构成员、结构标记、和普通变量可以采用相同的名字,不会冲突
    
    struct声明定义了一种数据类型
    
    在标记结构成员结束的右花括号之后可以跟一个变量表
    
    struct{ ... } x,y,z;
    这和
    int x,y,z
    具有类似的意义,这两个声明都将x、y与z声明为指定类型的变量,并分配存储空间
    
    如果结构声明后面不带变量表,则不需要为它分配存储空间,它仅仅描述了一个结构的模板
    
    如果结构声明中带有标记,那么在以后定义结构实列时便可以使用该标记定义
    
    struct point pt;
    
    在表达式中可以通过下列形式引用某个特定的结构中的成员
    结构名.成员
    
    结构可以嵌套
    

      

    6.2结构与函数

    结构的合法操作只有几种:
    
    作为一个整体复制和赋值
    通过&运算符去 地址,访问其成员
    复制和赋值包括向函数传递参数以及从函数返回值
    结构之间不可以进行比较
    可以用一个常量成员值列表初始化结构
    自动结构也可以通过赋值初始化
    
    如果传递给是的结构很大,使用指针的效率通常比复制整个结构的效率高
    
    结构指针类似于普通变量指针 声明
    struct point *pp;
    
    将定义一个指向struct point类型的指针
    
    如果pp指向一个point结构,那么*pp即为该结构
    而*(pp).x和*(pp).y则是结构成员
    
    *(pp).x中圆括号是必须的,因为结构成员运算符"." 的优先级比"*"的优先级高
    表达式 *pp.x含义等于 *(pp.x) ,x不是指针,所以是非法的
    
    结构指针的使用频率非常高,为了方便,C语言提供另一种简写
    p->结构成员
    
    在所有的运算符中4个优先级最高:
    结构运算符. 和->
    函数调用的()
    已经下标[] 
    
    表达式  ++pt->len
    将增加len的值,而不是增加pt的值,其中隐含的括号关系 ++(pt->len)
    

      

    6.3结构数组

    数组的长度在编译时已经完全确定,它等于数组项的长度乘以项数
    
    C语言提供了一个编译时计算任一对象的长度的运算符 sizeof
    
    表达式 
        sizeof 对象
    或  
        sizeof(类型名)
    将返回一个整形值,他等于指定对象或类型占用的空间字节数
    
    严格来说sizeof返回的是无符号整形,其类型为size_t
    
    条件编译语句#if中不能使用sizeof,因为预处理器不对类型名进行分析
    
    但预处理器并不计算#define语句中的表达式,因此 #define中使用sizeof是合法的
    

      

    6.4指向结构的指针

    千万不要认为结构的长度等于各成员长度的和。因为不同的对象有不同的对齐要求。
    所以结构中可能会出现未命名的"空穴"(hole)
    
    例如:
     
    struct{
       char c;
       int i; 
    } 
    
    可能需要8字节的存储空间,而不是5字节。使用sizeof可以返回正确的对象长度
    

      

    6.5自引用结构

    struct tnode{
       char *word;
       int count;
       struct tnode *left;
       struct tnode *right;
    }
    
    一个包含其自身实列的结构是非法的
    但是,下列声明是合法的
    
    struct tnode *left;
    它将left声明为指向tnode的指针,而不是tnode本身
    

      

    6.6表查找

    散列查找法: 将输入的名字转换为一个小的非负整数,该整数随后将作为一个指针数组的下标
    数组的每个元素指向某个链表的表头,链表中的各个块用于描述具有该散列值的名字,如果没有名字散列到该值,则数组元素的值为NULL
    
    unsigned hash(char *s){
      unsigned hashval;
        for(hashval=0; *s != '\0';s++)
        hashval = *s+31*hashval;
        return hashval % HASHSIZE;
    }
    
    由于在散列计算时采用的是无符号算术运算,因此保证了散列值非负
    

      

    6.7类型定义

    C语言提供了一个typedef的功能,用来建立新的数据类型名
    例如:
    typedef int Length;
    将Length 定义为何int具有同等意义的名字。
    类型Length可用于类型什么、类型转换等
    
    类似于
    typedef char *String
    将String定义为和char *或字符指针同义,此后,便可以在类型声明和类型转换中使用String
    
    typedef中声明的类型在变量名的位置出现,而不是紧接着typedef之后
    
    从任何意义上讲,typedef声明并没有创建一个新类型,它只是为某个已存在的类型增加了一个新的名字
    
    实际上typedef类似于#define语句,但由于typedef是编译器解释的,因此他的文本替换功能要超过预处理的能力
    
    除了表达式更简洁外,typedef使用还有两个重要原因
    
    首先它可以是程序参数化,以提高程序的可移植性
    第二是一位程序提供更好的说明性---Treeptr类型显然比一个声明为指向复杂结构的指针更容易让人理解
    

      

    6.8联合

    联合是可以在不同时刻保存不同类型和长度的对象的变量,编译器负责跟踪对象的长度和对齐要求。
    
    联合提供了一种方式,在单块存储区中管理不同类型的数据,而不需要程序中嵌入任何机器有关的信息
    
    例如:
    union u_tag{
       int ival;
       float fval;
       char *sval;
        
    } u;
    
    变量u必须足够大,以保存3种类型中最大的一种,具体长度同具体的实现有关
    
    这些类型中的任何一种类型的对象都可以赋值给u,且可使用在随后的表达式中,但必须保证是一致的:
    读取的类型必须是最近一次存入的类型。
    
    程序员负责跟踪当前保存在联合中的类型
    
    如果保存的类型和读取的类型不一致,其结果取决于具体的实现
    
    联合可以使用在结构和数组中,反之亦可
    
    
    实际上,联合就是一个结构,他的所有成员相对于基地址偏移量都为0
    
    此结构空间要大到足够容纳最宽的成员。
    
    并且,其对齐方式要适合联合中所有的类型的成员。
    
    对联合允许的操作与对结构允许的操作相同:
    
    作为一个整体单元进行复制 赋值 取地址及访问成员
    
    联合只能用第一个成员类型的值进行初始化,因此,联合u只能用整数进行初始化
    

      

      

    6.9 位字段

    在存储空间很宝贵的情况下,有可能需要将多个对象保存在一个机器字中。一种常用的方法是,使用类似于编译器符号表的单个二进制位标志集合。
    
    外部强加的数据格式也经常需要从字的部分位中读取数据
    
    考虑编译器中符号表操作的有关细节
    
    程序中的每个标识符都有与之相关的特定信息
    
    C语言提供了一种直接定义和访问一个字中的位字段的能力,而不需要通过按位操作
    
    位字段(bit-field)或简称字段,是字中相邻位的集合
    
    某些机器上字段的分配是从字的左端至右端进行的,而某些机器相反。
    

      

  • 相关阅读:
    学就要学好 就要学明白
    URL的基础
    各种waf识别
    Linux命令行上的上传和下载文件命令
    Linux服务器安全加固(三)
    Linux服务器安全加固(二)
    Linux服务器安全加固(一)
    Centos7配置SNMP服务
    Windows Server 系统通用安全基线配置详细
    Windows Server 2016 部署AD域控制器及添加AD域控制器
  • 原文地址:https://www.cnblogs.com/dafume/p/7803519.html
Copyright © 2011-2022 走看看