2016-07-27 15 views
13

Bir yapının, iyi hizalanmışsa veya boşluk içeriyorsa, derleme zamanında kontrol edilmesi konusunda bir sorunum var. Kontrol, ek test kodunda yapılabilir, ancak gerçek uygulama kodunda "paketlenmiş" veri istemiyorum. C++ 'da bir yapının iyi hizalanmış olduğunu veya boşluklar içerdiğini kontrol edin

Bu

korumaları içerir tipik bir örnek, başlık dosyası (MyData.h) aşağıdaki gibidir: Bir olası çözüm bulundu

#ifndef MYDATA_H_ 
#define MYDATA_H_ 

struct uneven 
{ 
    int bla_u32; 
    short bla_u16; 
    char bla_u8; 
    /* <-- this gap will be filled in the unpacked version */ 
}; 

#endif // MYDATA_H 

- aşağıya bakınız.

Sorular:

  • yapı uneven zaman derlemek de Açılmamış meslektaşı ile karşılaştırıldığında bayt farklı sayıda olup olmadığını kontrol etme zarif bir yolu var mı?

  • C'de (ad alanı kullanmadan) çalışacak bir çözüm bile olabilir mi?

+1

Diğer test kodlarında kontrol yapıldığında ne demek istiyorsunuz? İddiayı kodunuza yerleştirme konusunda kontrol sahibi olmak ister misiniz? Aksi takdirde, derleme zamanını kontrol etmek istediğiniz her yeni yapının statik belirleme uygulamanızla birleştirilen (@Dutow'un önerdiği gibi) bir işlevi tanımlayabilirsiniz. – jcxz

+0

"kontrol, ek test kodunda yapılabilir" anlamına gelir, sadece kontrol (aynı zamanda statik iddia) serbest bırakılmış kod tabanının veya gerçek ürünün parçası olmayan ek c veya cpp dosyalarında yapılabilir (ör. Ek derleyici bayrakları kullanarak) veya gerçek sürümün parçası olmaması gereken bir şey) –

cevap

3

:

Bu çözüm aynı zamanda C çalışır

Başlık Dosya:

typedef struct 
{ 
    int bla_u32; 
    short bla_u16; 
    char bla_u8; 

    /* <-- this gap will be filled in the unpacked version */ 
} uneven; 

Kaynak Dosya:

#include "MyData.h" 

#define StaticAssert(cond, msg) switch(0){case 0:case cond:;} 

void checkSizes() 
{ 
    uneven unpacked_uneven; 
#pragma pack(push, 1) 
    #undef MYDATA_H_ // force re-including "MyData.h" 
    #include "MyData.h" 
#pragma pack(pop) 
    uneven packed_uneven; 
    StaticAssert(sizeof(unpacked_uneven) == sizeof(packed_uneven), "uneven contains gaps"); 
} 

StaticAssert'unuzu bir derneğin işlevine yerleştirebilirsiniz e zaman hatası.

+0

Örnek kodla eşleşmesi için Dutow çözümünü uyarladım - bence bu oldukça kesmek ama derleyici uyarısı olmasaydı bu ortak çözümle giderdim -Wpadded (bkz. [link] (http://stackoverflow.com/a/38613971/2056545)) –

2

I (nedense kötü ve çok zor) bir tek C++ ile çalışan sorununa çözüm değil, C. bulundu

#define StaticAssert(cond, msg) switch(0){case 0:case cond:;} 

#pragma pack(push, 1) 
namespace packed 
{ 
#include "MyData.h" 
} 
#pragma pack(pop) 

#undef MYDATA_H_ // force re-including "MyData.h" 
#include "MyData.h" 

void checkSizes() 
{ 
    StaticAssert(sizeof(packed::uneven) == sizeof(uneven), "uneven contains gaps"); 
} 

Bu StaticAssert makro verilen düzensiz yapı verileri için başarısız - olarak Paketlenmiş sürümün boyutu 7 bayttır ve paketlenmemiş (normal) sürüm 8 bayttır. Yapının sonunda ek bir char eklenirse, sınama başarılı olur - her iki sürüm de 8 bayta sahiptir.

+0

Yuvalanmış bir yapı kullanarak ad alanından kaçınabilirsiniz. – Dutow

+0

@Dutow C uyumluluğuna yardımcı olmadığından, Yapıların C – user2079303

+1

kapsamında bir kapsamı olmadığından, alternatif olarak, # # # # # # # # # # # # # # #, – MSalters

4

Hem C hem de C++ için çalışan bir derleyici özel çözümü: GCC, hizalama nedeniyle boyutu değiştiren her tanım için bir uyarı üreten -Wpadded uyarı seçeneğine sahiptir.

Onun yerine bir ad ( on ideone) bir fonksiyonu kullanabilirsiniz
+0

Bu harika - ve çok daha kolay! :) - ne yazık ki gcc özgüdür. Bunun yerine -Wpadded doğrudan makefile ben '# Pragma GCC teşhis push' yapılar ile ' # Pragma GCC teşhis hatası "-Wpadded" ' .... kod kullanmak istiyorsunuz (sistemin kontrolünü içerir önlemek için) '#pragma GCC tanılama pop' 0 –

İlgili konular