代码改变世界

菜鸟C++自学笔记 【结构与联合】

2010-10-12 17:34  Terry_龙  阅读(2518)  评论(7编辑  收藏  举报

c++程序员可以定义结构(structure)中的变量集合。结构将相关数据封装成一个聚集(aggregate)。程序可以用类似于处理内部数据类型的方法来处理结构。另外一种数据聚集被称为联合(union),它定义一个可能具有多个名字和类型的变量。大纲为:

  • 声明结构
  • 定义结构变量
  • 引用struct成员
  • 初始化结构
  • 结构的内部结构
  • 结构与函数
  • 联合
  • 初始化联合
  • 匿名联合

1.声明结构

可以用关键字struct 声明一个结构、给结构命名并声明结构中的数据类型,如下如示:

 

struct Date{
    
int month,day,year;
};

 

 

结构声明以关键字struct 开始,后面有结构名称。结构由称做结构成员(Member)的变量组成。结构声明包括在大括号中,用分号结束声明,结构声明不占用存储器空间(即前面代码不会创建任何变量),它只定义结构的格式供程序以后使用。

2.定义结构变量

如上,通过使用关键字struct 来定义结构变量,如果你之前有定义过结构可以直接使用结构的变量名称使用此结构,但有一点,假如你程序中存在相同的变量名称的变量,则你必须的注明要使用的变量是结构还是其他类型,如下:

 

struct Date{
    
int month,day,year;
};

void Date(){}

 

 

3.引用struct成员

类似JAVA或者c#一样我们可以直接使用结构变量然后通过“.”来引用结构成员,下面提供一段引用结构的DEMO:

 

#include "StdAfx.h"
#include 
<iostream>


struct Date{
    
int month,day,year;
};
 
int main(int argc, char* argv[])
{  
 
    Date dt;
    dt.month
=10;
    dt.day
=12;
    dt.year
=2010;
    std::cout
<<dt.month<<"/"<<dt.day<<"/"<<dt.year<<"\n";
    
return 0;
}
 

 

 

去行效果如下:

 

4.初始化结构

如上所示,我们可以使用如下代码初始化结构:

 

#include "StdAfx.h"
#include 
<iostream>


struct Date{
    
int month,day,year;
};
 
int main(int argc, char* argv[])
{  
    Date dt
={10,12,2010};
    std::cout
<<dt.month<<"/"<<dt.day<<"/"<<dt.year<<"\n";
    
return 0;
}

 

运行效果:

Tip:main函数中用大括号包起来、并用逗号分隔的表达式列表是结构的初始化列表。每个表达式初始化一个结构成员。表达式类型必须与成员类型相匹配。其数量可以少于结构成员的数量,但不能多于结构成员的数量。否则将报此错误:too many initializers 。初始化数少于成员数量,编绎器将自动为其赋0。

5.结构的内部结构

一个结构可以把其他结构作为成员,如下代码:

 

#include "StdAfx.h"
#include 
<iostream>


struct Date{
    
int month,day,year;
};
struct employee{
    
int emplNO;
    
float salary;
    Date birthday;
};
 
int main(int argc, char* argv[])
{  
    employee joe
={123,5000,{10,12,2010}};
    std::cout
<<"工号为:"
        
<<joe.emplNO
        
<<"\n薪资为:"
        
<<joe.salary
        
<<"\n生日为:"
        
<<joe.birthday.month<<"/"<<joe.birthday.day<<"/"<<joe.birthday.year<<"\n";
    
return 0;
}
 

 

 

运行效果如图:

 

如以上代码,程序中声明了两个结构,第二个结构employee把第一个结构Date的实例作为成员。当初始化employee 这个结构时,遇到了Date 这个结构,那么也必须像上面一样添加一对大括号然后初始化它。使用的时候直接通过“.”连接彼此,即可将对应的结构成员调出来。

6.结构与函数

函数可以将结构作为形参,也可以返回结构。我们有时需要传递一个结构的私有副本。被调用函数可能改变结构数据,而调用函数却要保留数据原来的值。下面给出一段DEMO将实现函数返回结构让结构变量接收将输出相应数据:

 

#include "StdAfx.h"
#include 
<iostream>


struct Date{
    
int month,day,year;
};
Date getToday(
void);
void printDate(Date); 
 
int main(int argc, char* argv[])
{  
    Date dt
=getToday();
    printDate(dt);
    
return 0;
}


Date getToday(){
    Date dt;
    std::cout
<<"Enter today;";
    std::cin
>>dt.month>>dt.day>>dt.year;
    
return dt;
}

void printDate(Date dt){
    std::cout
<<dt.month<<"/"
        
<<dt.day<<"/"
        
<<dt.year<<"\n";
}

 

运行效果如图:

 

7.联合

从表面上看,联合和结构几乎一样,只是关键字由struct换成了union。联合和结构之间的区别在于结构定义相邻数据成员和聚集,而联合定义所有数据成员共享的存储器地址。联合一次只含有一个值,即一个成员类型的值,所有成员的位置都从同一存储器单元开始。

下面给出一段代码:

 

#include "StdAfx.h"
#include 
<iostream>

union Holder{
    
char holderChar;
    
short int holdint;
    
long int holdlong;
    
float holdfloat;

};

void DisplayHolder(Holder,char*);

int main(int argc, char* argv[])
{  
    Holder holder;
    holder.holderChar
='x';
    DisplayHolder(holder,
"Char");


    holder.holdint
=13;
    DisplayHolder(holder,
"int");

    holder.holdlong
=7654321;
    DisplayHolder(holder,
"long");

    holder.holdfloat
=1.23;
    DisplayHolder(holder,
"float");
 
    
return 0;
}

void DisplayHolder(Holder hold,char* tag){
    std::cout
<<"--Initialized"<<tag<<"---\n";
    std::cout
<<"holdChar-->"<<hold.holderChar<<"\n";
    std::cout
<<"holdint-->"<<hold.holdint<<"\n";
    std::cout
<<"holdlong-->"<<hold.holdlong<<"\n";
    std::cout
<<"holdfloat-->"<<hold.holdfloat<<"\n";
}

 

 

运行效果如图:

如上代码所示,对一个联合成员的改变会同时改变其他成员。当我们给一个特定成员赋值时,其他成员的值就失去了明确意义,因为它们都被前者新赋的值取代了。

8.初始化联合

我们只能对联合的第一个变量进行初始化。初始化由大括号括起来,并且只能有一个数据值,该数据值的类型必须与联合的第一个成员类型匹配,初始联合大致跟结构一样,可以使用“{}”为其内部成员变量赋值。如下代码:

 

Holder holder={'x'};

 

 

Tip:因为联合只能对第一个成员初始化,如果你初始化时多于一个值 的话将会报下面的错:too many initializers。

如果联合的第一个成员是一个结构,初始化的表达式中可能包括多个用于初始化结构的表达式,如下代码 :

 

代码
struct Date
{
    
int day,month,year;
};
union Holder{
    Date date;
    
char holderChar;
    
short int holdint;
    
long int holdlong;
    
float holdfloat;

};
int main(int argc, char* argv[])
{  
    Holder holder
={{12,10,2010}};
}

 

 

9.匿名联合

c++程序可以声明未命名的联合,利用这一特性,可以节省空间或有意识地重定义一个变量,看下面这段代码:

 

#include "StdAfx.h"
#include 
<iostream>
int main(int argc, char* argv[])
{  
    union {
        
int quantity_todate;
        
int quantity_balance;
    };
    std::cout
<<"Enter quantity to date:";
    std::cin 
>>quantity_todate;
    std::cout
<<"Enter quantity sold:";
    
int quantitiy_sold;
    std::cin
>>quantitiy_sold;
    quantity_balance
=quantity_todate-quantitiy_sold;
    std::cout
<<"quantity_balance="<<quantity_balance<<"\n";

    
return 0;
}

 

 

输入结果:

 

Tip:如果在程序中给联合命名只是为了支持联合,那么在引用联合成员时可以利用上述这一特性消除许多联合名的前缀。全局匿名联合必须被声明为静态的。