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)

  • 相关阅读:
    数据库表结构变动发邮件脚本
    .net程序打包部署
    无法登陆GitHub解决方法
    netbeans 打包生成 jar
    第一次值班
    RHEL6 纯命令行文本界面下安装桌面
    C语言中格式化输出,四舍五入类型问题
    I'm up to my ears
    How to boot ubuntu in text mode instead of graphical(X) mode
    the IP routing table under linux@school
  • 原文地址:https://www.cnblogs.com/ikaka/p/4109121.html
Copyright © 2011-2022 走看看