baidut
11/15/2014 - 1:24 PM

注意结构体分配偏移量时的字节对齐问题 C++可以为结构体定义方法,与class的唯一区别就是默认public

注意结构体分配偏移量时的字节对齐问题 C++可以为结构体定义方法,与class的唯一区别就是默认public

#include <iostream>
using namespace std;

#include <stdio.h> // sprintf

typedef unsigned char u_char;

typedef struct ip_address{
    u_char  byte1;
    u_char  byte2;
    u_char  byte3;
    u_char  byte4;

    char* toString(){
    	char* str = new char(16);
    	sprintf(str,"%d.%d.%d.%d",byte1,byte2,byte3,byte4);
        return str;
    }
    bool operator == (const struct ip_address& other) const{
       return       (byte1 == other.byte1)
               &&   (byte2 == other.byte2)
               &&   (byte3 == other.byte3)
               &&   (byte4 == other.byte4);
    }
    friend ostream &operator<< (ostream &out,struct ip_address &a) { // &a
       //out<<a.byte1<<'.'<<a.byte2<<'.'<<a.byte3<<'.'<<a.byte4; 这句有问题,造成无法输出
       out << a.toString();// 注意这里是out 不是cout 还有a.byte1,不是byte1
       return out;// 注意要返回
    }
}ip_address;

int main() {
	
	ip_address ip1 = {198,163,2,1};
	ip_address ip2 = {198,168,22,56};
	
	cout<< "u_char:" << sizeof(u_char)<<endl ;
	cout<< "ip_address:" << sizeof(ip_address) << endl; // 方法不占空间!
	
	cout<<ip1.toString()<<endl;
	cout<<ip1<<endl;
	cout<<ip2.toString()<<endl;
	cout<<ip2<<endl;
	
	if(ip1==ip2)
		cout<<"ip1 == ip2" <<endl;
	else cout<< "ip1 != ip2" <<endl;
	ip_address ip3 = {198,163,2,1};
	if(ip1==ip3)
		cout<<"ip1 == ip3" <<endl;
	else cout<< "ip1 != ip3" <<endl;
	return 0;
}

/*
Success	time: 0 memory: 3472 signal:0 
Output:
u_char:1
ip_address4
198.163.2.1
198.163.2.1
198.168.22.56
198.168.22.56
ip1 != ip2
ip1 == ip3
*/
#include <iostream>
using namespace std;

typedef unsigned char u_char;
typedef unsigned short int u_short;
typedef unsigned int u_int;

/*
字节对齐原则
结构体默认的字节对齐一般满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset,即每个成员的起始地址)都是成员自身大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
注意:当结构体成员里面有数组成员时,如int a[10],要看成10个整形变量才参与计算。
*/
typedef struct{
    u_char flag;
    u_short version;
    u_short command;
    u_short sequence; 
    u_int   number;
}oicq_packet1;

typedef struct{
    u_short version;
    u_short command;
    u_short sequence; 
    u_int   number;
}oicq_packet2;

typedef struct{
    u_char flag;
    u_char padding;  // 2) 
    u_short version;
    u_short command;
    u_short sequence; 
    u_int   number;
}oicq_packet3;

typedef struct{
    u_short version;
    u_short command; 
    u_short sequence;
    u_short padding; // 2) 
    u_int   number;
}oicq_packet4;

int main() {
	cout << sizeof(u_char) << endl;
	cout << sizeof(u_short) << endl;
	cout << sizeof(u_int) << endl;
	cout << sizeof(oicq_packet1) << endl;
	cout << sizeof(oicq_packet2) << endl;
	cout << sizeof(oicq_packet3) << endl;
	cout << sizeof(oicq_packet4) << endl;
	return 0;
}