问题描述
C++中定义结构体:#if(defined(AIX)&&defined(__xlC__))#pragmaoptionsalign=packed#else#pragmapack(1)#endiftypedefstruct{charszServerName[33];intnProtocal;charszAddress[33];intnPort;charszSendQName[33];charszReceiveQName[33];charszReserved[33];}tagConnectOption;sizeof(tagConnectOption)=173
C#中定义publicstructtagConnectOption{[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szServerName;publicInt16nProtocal;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szAddress;publicInt16nPort;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szSendQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReceiveQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReserved;publictagPConnectOption(intserNameMax,intdesMax){szServerName=newbyte[33];nProtocal=0;szAddress=newbyte[33];nPort=0;szSendQName=newbyte[33];szReceiveQName=newbyte[33];szReserved=newbyte[33];}}Marshal.SizeOf(tagPConnectOption)=172
进一步publicstructtagConnectOption{[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szServerName;//publicInt16nProtocal;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szAddress;publicInt16nPort;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szSendQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReceiveQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReserved;publictagPConnectOption(intserNameMax,intdesMax){szServerName=newbyte[33];//nProtocal=0;szAddress=newbyte[33];nPort=0;szSendQName=newbyte[33];szReceiveQName=newbyte[33];szReserved=newbyte[33];}}Marshal.SizeOf(tagPConnectOption)=168
publicstructtagConnectOption{[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szServerName;//publicInt16nProtocal;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szAddress;//publicInt16nPort;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szSendQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReceiveQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReserved;publictagPConnectOption(intserNameMax,intdesMax){szServerName=newbyte[33];//nProtocal=0;szAddress=newbyte[33];//nPort=0;szSendQName=newbyte[33];szReceiveQName=newbyte[33];szReserved=newbyte[33];}}Marshal.SizeOf(tagPConnectOption)=165
在C++中的字长很容易理解,33*5+4*2=173,为什么在C#中少了一个字节变成172了呢?进一步当C#中没有定义Int16时,为33*5=165容易理解;定义一个Int16时为168在原来基础上增加了3字节???费解啊费解啊
解决方案
解决方案二:
lz精神让我pf.
解决方案三:
具体你可以看下struct在各语言的说明
解决方案四:
和内存对齐有关系,第一段C++程序中,#pragmapack(1)指定了对齐时封装大小是1,你可以试试设成8应该就和C#的结果一样了。(印象中封转大小默认是8)在C#中,如果没有指定struct的内存对齐方式,默认为LayoutKind.Sequential,封装大小为8参考一下这篇文章:,里面讲解了对齐规则。解释一下为何下面这段占用168[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szServerName;//publicInt16nProtocal;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szAddress;publicInt16nPort;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szSendQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReceiveQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReserved;
首先,[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szServerName;相当于写了33个byte在这里,对齐是按照每个byte来对齐的,不是按照整个数组对齐,byte长度是1,1<8,按照1对齐,这就能导致szAddress从第33字节开始对齐,而不是从第40字节而Int16占用两个字节,按照2来对齐,所以整个struct在内存中的布局是[0szServerName32][33szAddress65][66nPort67][68szSendQName100][101szReceiveQName133][134szReserved166][167]最后的167是补了一个空字节,因为要将整个结构体大小控制为8的倍数。其他几个类似,只要弄明白了布局规则,就OK了。
解决方案五:
最后的167是补了一个空字节,因为要将整个结构体大小控制为8的倍数。其他几个类似,只要弄明白了布局规则,就OK了。-------------------------------------------------------------这句话说错了,应该是控制为2的倍数,因为是“结构的整体对齐规则:在数据成员完成各自对齐之后,结构本身也要进行对齐,对齐将按照pack指定的数值和结构最大数据成员长度中,比较小的那个进行”也就是Int16的长度2
解决方案六:
谢谢ivorstar的耐心回答!照此解释publicstructtagConnectOption{[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szServerName;publicInt16nProtocal;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szAddress;publicInt16nPort;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szSendQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReceiveQName;[MarshalAs(UnmanagedType.ByValArray,SizeConst=33)]publicbyte[]szReserved;publictagPConnectOption(intserNameMax,intdesMax){szServerName=newbyte[33];nProtocal=0;szAddress=newbyte[33];nPort=0;szSendQName=newbyte[33];szReceiveQName=newbyte[33];szReserved=newbyte[33];}}Marshal.SizeOf(tagPConnectOption)=172
[0szServerName32][33nProtocal34][35szAddress67][68nPort69][70szSendQName102][103szReceiveQName135][136szReserved168][169]这个为什么不是170而是172呢?
解决方案七:
自己醒悟过来了,上面结构中应该是逐项对齐的,即布局为:1),数据成员各自对齐[0szServerName32][33nProtocal34][35][36szAddress68][69nPort70][71][72szSendQName104][105szReceiveQName137][138szReserved170]2),数据成员完成各自对齐,结构本身进行对齐[0szServerName32][33nProtocal34][35][36szAddress68][69nPort70][71][72szSendQName104][105szReceiveQName137][138szReserved170][171]对吗?有待高手肯定
解决方案八:
顶
解决方案九:
顶
解决方案十:
顶
解决方案十一:
再顶一下回家了,明天来看
解决方案十二:
引用6楼Kinpring的回复:
自己醒悟过来了,上面结构中应该是逐项对齐的,即布局为:1),数据成员各自对齐[0szServerName32][33nProtocal34][35][36szAddress68][69nPort70][71][72szSendQName104][105szReceiveQName137][138szReserved170]
1),[0szServerName32][33][34nProtocal35][36szAddress68][69][70nPort71][72szSendQName104][105szReceiveQName137][138szReserved170]……可以再参照参照上面链接里的例子,在考虑自身布局的时候,nProtocal总是努力把自己放在一个好找的位置——起始位置=Min(自身长度,封装长度)的倍数
解决方案十三:
该回复于2008-04-04 11:28:37被版主删除
解决方案十四:
明白了谢谢ivorstar!