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)

时间: 2024-10-13 15:17:14

struct的初始化,拷贝及指针成员的使用技巧的相关文章

C++11 指针成员与拷贝构造(浅拷贝与深拷贝)

[1]浅拷贝 一直以来,设计一个类,个人认为,最能体现水平的地方在于:类中含有指针成员变量. 如下一个典型的浅拷贝示例: 1 #include <iostream> 2 using namespace std; 3 4 class HasPtrMem 5 { 6 public: 7 HasPtrMem() : d(new int(0)) 8 {} 9 ~HasPtrMem() 10 { 11 delete d; 12 d = nullptr; 13 } 14 15 int* d; 16 };

15.含有指针成员的类的拷贝(copy constructor)

http://zhedahht.blog.163.com/blog/static/25411174200722710364233/ http://www.cnblogs.com/t427/archive/2012/08/10/2633133.html http://blog.csdn.net/gamecreating/article/details/5382902 http://www.cppblog.com/xczhang/archive/2008/01/21/41569.html 题目:下面

c语言中struct的初始化

C++中的struct已经和class一样,可以用构造函数初始化. C语言中的struct怎么初始化呢? typedef struct _TEST_T {        int i;        char c[10];}TEST_T; TEST_T gst  = {1, “12345”};//可以初始化,设置i为1,s为一个字符串. TEST_T gst  = {1};//初始化个数少于实际个数时,只初始化前面的成员. TEST_Tgst  = {.c=“12345”};//有选择的初始化成员

C++ Primer 学习笔记_57_类与数据抽象 --管理指针成员

复制控制 --管理指针成员 引言: 包含指针的类需要特别注意复制控制,原因是复制指针时只是复制了指针中的地址,而不会复制指针指向的对象! 将一个指针复制到另一个指针时,两个指针指向同一对象.当两个指针指向同一对象时,可能使用任一指针改变基础对象.类似地,很可能一个指针删除了一对象时,另一指针的用户还认为基础对象仍然存在.指针成员默认具有与指针对象同样的行为. 大多数C++类采用以下三种方法之一管理指针成员: 1)指针成员采取常规指针型行为:这样的类具有指针的所有缺陷但无需特殊的复制控制! 2)类

C++ 带有指针成员的类处理方式

在一个类中,如果类没有指针成员,一切方便,因为默认合成的析构函数会自动处理所有的内存.但是如果一个类带了指针成员,那么需要我们自己来写一个析构函数来管理内存.在<<c++ primer>> 中写到,如果一个类需要我们自己写析构函数,那么这个类,也会需要我们自己写拷贝构造函数和拷贝赋值函数. 析构函数: 我们这里定义一个类HasPtr,这个类中包含一个int 类型的指针.然后定义一个析构函数,这个函数打印一句话. HasPtr.h 类的头文件 1 #pragma once 2 #if

struct {0}初始化

#include <iostream> struct MyStruct { MyStruct(int a) { a = b = 0; } int a; int b; }; int main() { MyStruct my = {0};//列表初始化只适合非聚合结构体,所以这样不行,所以需要将上面的构造函数去掉,但发现把struct换成class还是不行的,莫非class天生就是聚合的? getchar(); return 0; }网上搜到的解释 4.1.3 聚合(aggregate) int

struct的初始化

1.struct的初始化可以使用类似数组的方式,如下:struct Student{ int _Age; string _Name;};Student stu = {26,"Andy"};2.有两个地方需要注意: a.顺序要保持一致,如下: Student stu = {"Andy",26}; 编译报错 b.后面的可以不初始化 Student stu = {26}; 只初始化_Age3.考虑下面的情况,Student当中有个字段,表示Student对象的大小,而在D

C++:用成员初始化列表对数据成员初始化

1.在声明类时,对数据成员的初始化工作一般在构造函数中用赋值语句进行. 例如: class Complex{ private: double real; double imag; public: Complex(double r,double i) //声明构造函数原型 { ........... } }; Complex::Complex(double r,double i) //在构造函数中用赋值语句对数据成员赋初值 { real = r; imag = i; } 2.另一种初始化数据成员的

Java中的初始化顺序(静态成员、静态初始化块,普通成员、普通初始化块、构造函数)

本文链接    http://blog.csdn.net/xiaodongrush/article/details/29170099 参考文章     http://my.oschina.net/leoson/blog/103251 1. 一个类中的初始化顺序 (静态变量.静态初始化块)=>(变量.初始化块.构造器). 2. 两个具有继承关系类的初始化顺序 父类的(静态变量.静态初始化块)=> 子类的(静态变量.静态初始化块)=> 父类的(变量.初始化块.构造器)=> 子类的(变量