zoukankan      html  css  js  c++  java
  • C和指针 第十章 结构和联合 (一)

    结构体:

    聚合数据类型是指,能够同时存储超过一个的单独数据,C语言中有两个聚合数据类型,数组和结构体。数组中储存的类型必须相同,元素通过下标和指针引用来访问的。

    结构体也是一些值的集合,但是结构体中每个元素的值的类型可以不同,每个元素都有自己的名字,和整数字符一样,结构体也是标量类型

    结构体声明:

    struct  tag  {  memeber-list   }  variable-list;
    

    结构体声明要包含所有的成员的类型和名字

    struct  tag {
      char *name;
      int    *age;
    } people;
    

    其中,tag时标签字段,可以在后续的声明中使用tag代表成员列表:

    struct tag animal;
    

    此处的声明和上面的people一样,animal和people对于编译器来说,是两个不同的类型的。

    如果需要定义相同的类型,可以通过typedef来创建新类型:

    typedef struct  {
      char *name;
      int    *age;
    } animal;
    

    现在animal是一新的结构体类型,可以直接使用他进行赋值

    animal dog;
    

    结构体的成员:

    结构体的成员可以时标量,指针,和其他结构体等等,但是不可以是自身类型的成员,即自己。结构体成员可以通过点号访问

    #include <stdio.h>
    
    typedef struct {
        char *name;
        int   age;
    } animal;
    
    int main()
    {
        animal dog = { "ted", 3};
        printf("%s", dog.name);
    
        return 0;
    }
    

    运行结果:

     

    如果是指向结构体的指针,可以先解引用操作,然后在使用点操作符,C有个快捷的方法,使用 -> 访问结构体指针指向的结构体成员,上面代码可以如下改写:

    animal dog = { "ted", 3};
    animal *ptr = &dog;
    printf("%s", ptr -> name);
    

    结构体时不可以包含自身类型的成员的,不过可以包含指向自己类型的指针的。

    #include <stdio.h>
    struct SELF {
        char *name;
       //selfPtr是指向自身类型的指针 struct SELF * selfPtr; } animal; int main() { struct SELF dog = { "ted", NULL}; struct SELF cat = {"mimi", &dog}; printf("%s", cat.selfPtr -> name); return 0; }

    运行结果:

    注意:下面的这种声明是非法的,因为类型名直到声明结束才定义

    typedef struct {
        char *name;
        struct SELF * selfPtr;
    } SELF;
    

    解决方法是添加一个结构标签。

    typedef struct SELF {
        char *name;
        struct SELF * selfPtr;
    } animal;
    

    如果两个结构体相互依赖引用,一个结构体包含另一个结构体,另一个结构体包含这个结构体。那么可以使用不完整声明,先声明一个结构体作为标识符,然后使用他,然后把成员和标识符关联。

      //声明表示符,在A中使用
        struct B;
        struct A {
            struct B *bPtr;
        };
    
        //关联成员
        struct B {
            struct A *aPtr;
        };
    

    结构体的初始化,类似数组,大括号内部包含逗号分割的初始值,如果初始值列表不够用,剩余的结构成员将使用缺省值初始化。

        struct {
            char *name;
            int age;
        } me = {"yangxunwu", 24};
    

    结构体的储存分配:

    由于结构体类别的成员的类型可以不一样,编译器在给成员列表分配内存时,一个接着一个的分配,只有当储存成员需要满足边界对齐时,成员之间会出现储存间隙。系统禁止在一个结构的起始位置跳过几个字节来满足边界对齐要求,因此所有的结构的起始储存位置,必须是边界要求最严格的数据类型所要求的位置,如下:

    #include <stdio.h>
    
    int main()
    {
        struct {
            char ch1;
            int age;
            char ch2;
        } stc1;
    
        struct {
            int age;
         char ch1;
         char ch2; } stc2; printf("%lu %lu", sizeof(stc1), sizeof(stc2)); return 0; }

    可以通过重新排序成员,让边界对齐要求高的先出现,如上运行:

    int类型占四个字节,char占一个字节,因为要从起始位置对齐,所以stc1的第一个char占4字节,而stc2中,age占四个字节,ch1和ch2在一起占四个字节。sizeof可以返回一个long unsigned int表示整个结构体长度。

    stddef.h宏 offsetof(type, member) 返回指定成员,距离结构开始偏移几个字节。
    

     

    #include <stdio.h>
    #include <stddef.h>
    
    int main()
    {
        struct stc1 {
            char ch1;
            int age;
            char ch2;
        } ;
    
        struct stc2 {
            int age;
            char ch1;
            char ch2;
        } ;
    
        printf("%lu %lu", offsetof(struct stc1, ch2), offsetof(struct stc2, ch2));
    
        return 0;
    }
    

     运行:

  • 相关阅读:
    SAP 锁对象
    smartforms取消word为默认编辑器
    abap 配置 zconfig
    Ant步步为营(1)解压本地的zip包
    点击页面出现文字动画
    js简单实现累加
    github发布线上项目
    jsonp的实现
    js操作class
    js开发实用技巧
  • 原文地址:https://www.cnblogs.com/yangxunwu1992/p/5831182.html
Copyright © 2011-2022 走看看