zoukankan      html  css  js  c++  java
  • struct的初始化,拷贝及指针成员的使用技巧

    struct是C中重要的ADT。但是在一般讲C的书中,往往只介绍了struct的定义、顺序初始化及位域。
    本文将笔者曾经用到的、看到的知识点罗列出来,与大家分享。
    为了方便后面的介绍,先定义一个struct类型:
            struct User
            {
                int id;             //id
                char name[100];     //user name
                char *home;         //home directory
                int passwd;         //password
            };
    1 初始化
    struct数据有3中初始化方法:顺序,C风格及C++风格的乱序。
    1)顺序
    这种方法很常见,在一般的介绍C的书中都有介绍。顺序初始化的特点是: 按照成员定义的顺序,从前到后逐个初始化;允许只初始化部分成员;在被初始化的成员之前,不能有未初始化的成员;未显示初始化的自动设为0。
    eg:
            struct User oneUser = {10, "Lucy", "/home/Lucy"};
    初始化之后,oneUser各个成员的值为:
            oneUser.id = 10;
            oneUser.name = "Lucy";
            oneUser.home = "/home/Lucy";
            oneUser.passwd = 0;
    2)乱序(C风格)
    顺序的缺陷是必须按成员定义的顺序逐个初始化,不能间隔。而乱序的方式则很好的解决了这个问题,因为这种方式是按照成员名进行。
    eg:
            struct User oneUser = {
                                   .name = "Lucy",
                                   .id = 10,
                                   .home = "/home/Lucy"
                                  };
    3)乱序(C++风格)
    C++风格的乱序初始化方式跟C风格的一样,只是它更常用在C++代码里。
    eg:
            struct User oneUser = {
                                   name:"Lucy",
                                   id:10,
                                   home:"/home/Lucy"
                                  };
    不论是哪种方式,都允许只初始化部分成员;未被初始化的成员默认为0(指针类型的成员默认为NULL)。两种乱序初始化方法,既可以用在C代码中,也可以用在C++代码中。
    2 拷贝
    struct有两种拷贝方式,一是直接赋值(=),另一种是用memcpy等库函数实行内存拷贝。
    eg:
            struct Temp a, b;
            //Set value to members of b
            a = b;
            memcpy(&a, &b, sizeof(a));
    不管是哪种拷贝方式,都是将以&b开始的,大小为sizeof(struct Temp)的内存区域中的数据,简单地复制到以&a开始的,同样大小的内存区域。所以,这两种方式与按成员赋值是等价的:
            a.id = b.id;
            a.name = b.name;
            a.home = b.home;
            a.passwd = b.passwd;
    由此,我们不难看出,上面两种拷贝方式都属于浅拷贝。
    3 指针成员的两种使用技巧
    1) 为多个指针成员同时分配内存
    如果一个struct中有多个指针类型的成员,我们通常需要为每个指针逐个成员分配内存空间,并在使用完时释放它们;这样频繁调用malloc/free,难免让人生厌。如果在分配内存之前,每个指针所指向内存区域的大小是确定的,那么,我们可以为所有指针一次性分配内存区域;并在使用完后,一次性释放。
    eg:
           struct Inode
           {
              int id;
              char *file;
              int fie_len;
              char *path;
              int path_len;
              char *user;
              int user_len;
           };
           struct Inode data = {
                                .file_len = X,
                                .path_len = Y,
                                .user_len = X
                                };
           //Allocate memory
           data.file = (char *)malloc(data.file_len + data.path_len + data.user_len);
           data.path = data.file + data.file_len;
           data.user = data.path + data.path_len;
           //User
           ...
           //Free memory
           free(data.file);
    2)变长数组的另类实现
    将下面的定义
           struct File
           {
              TypeA dataA;
              ......
              char *data;
              TypeN dataN;        
           };
    改成:
           struct File
           {
              TypeA dataA;
              ......        
              TypeN dataN;  
              char data[0];     
           };
    即将指针成员换成大小为0的一维数组, 作为struct的最后一个成员(数据结构的可变部分必须作为最后一个成员),有两个优点:
    (1) 在紧邻struct处为data分配内存区域,这样在分配内存后无须为data赋值;
    (2) 利用数组的特性,以指针的方式通过越界访问data数组外的内存区域。
    eg:
           struct File *pVar = (struct File *)malloc(sizeof(struct File) + DATA_LEN);
           strncpy(pVar->data, "Source data", DATA_LEN);

     

    (转自:http://blog.chinaunix.net/uid-8735300-id-2016862.html)

  • 相关阅读:
    Linux常用命令及示例(全)
    linux下安装配置svn服务器
    Kafka、Redis和其它消息组件比较
    ORACLE定时备份方案
    mysql库表优化实例
    携程apollp快速部署DVE集群
    windows 安装Zookeeper 配置集群
    Ubuntu 18.04 LTS 修改Host,使用Host访问
    PowerShell因为在此系统中禁止执行脚本......
    常用第三方工具的Docker命令
  • 原文地址:https://www.cnblogs.com/ikaka/p/4109121.html
Copyright © 2011-2022 走看看