Mayor
							
								Специалист 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 «  : 04-05-2004 08:24 »   | 
								
								 | 
							  
							 
							В целях оптимизации под i386 , мне требуется заставить компилятор автоматически при объявлении структуры задавать смещение некоторых полей кратными 4 или  8 байтам  и также для  массивов требуются  структуры размером кратные  4 или 8 , например :
  struct r_elem{ c_elem a1; unsigned char data1[max_t]; unsigned char data2[max_r]; BYTE flags; unsigned int size; }
  где c_elem структура произвольного размера в целях оптимизации помещается в начало , max_t max_r могут от версии к версии варьировать , но смещения от начала r_elem до   data1 и data2 должны быть кратны 8 байтам ,смещение flags не имеет значения, смещение size д.б. кратно 4 байтам при этом размер структуры д.б. кратен 8
  Как об этом сообщить компилятору ? 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							1n c0de we trust 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							npak
							
						 | 
						
							
								  | 
								
									
									 « Ответ #1 : 05-05-2004 09:38 »   | 
								
								 | 
							  
							 
							Широко распространённый в мире C приём: сделать union с двумя полями.  Первое поле твоё, второе -- массив того размера, который нужен для выравнивания следующего поля. В примере ниже структура с двумя полями данных, причём второе выровнено на границу 64 бита.  Первое поле сидит внутри юниона, поэтому для него создаём макрос для удобства доступа. struct my_struct {     union     {         shord _my_field_1; /* My data field */         int8_t align_1[8];                /* Alignment 64 bits */     } _u1;          int my_field_2;                       /* This field is aligned to 64 bits */ };
  #define my_field_1 _u1._my_aligned_field
   
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 25-11-2007 20:08 от Алексей1153++ »
								 | 
								
									 
									Записан
								 | 
							  
							 
							
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							darkelf
							
								Молодой специалист 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #2 : 05-05-2004 14:07 »   | 
								
								 | 
							  
							 
							Вариант с #pragma #pragma pack(push, 4) struct my_struct  {     short my_field_1; /* My data field */      int my_field_2;     /* This field is aligned to 64 bits */  }; #pragma pack(pop)
   
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 25-11-2007 20:08 от Алексей1153++ »
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							npak
							
						 | 
						
							
								  | 
								
									
									 « Ответ #3 : 05-05-2004 14:29 »   | 
								
								 | 
							  
							 
							По-моему, в данном примере для выравнивания на 8 байт должно быть  К сожалению, это нестандартная фича компилятора от майкрософт.  Если в планах есть перенос на другую операционную систему/другой комилятор, то такой способ задать выравнивание может осложнить жизнь.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 25-11-2007 20:23 от Алексей1153++ »
								 | 
								
									 
									Записан
								 | 
							  
							 
							
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							Anonymous
							 
								Гость 
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #4 : 06-05-2004 16:40 »   | 
								
								 | 
							  
							 
							 К сожалению, это нестандартная фича компилятора от майкрософт.  Если в планах есть перенос на другую операционную систему/другой комилятор, то такой способ задать выравнивание может осложнить жизнь.
 в gсс v3.2 тоже работает, так что не такая уж нестандартная.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							npak
							
						 | 
						
							
								  | 
								
									
									 « Ответ #5 : 06-05-2004 17:37 »   | 
								
								 | 
							  
							 
							 К сожалению, это нестандартная фича компилятора от майкрософт.  Если в планах есть перенос на другую операционную систему/другой комилятор, то такой способ задать выравнивание может осложнить жизнь.
 в gсс v3.2 тоже работает, так что не такая уж нестандартная. А у меня не работает.  gcc на эту прагму не ругается, но игнорирует. В примере с union выравнивается правильно.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							npak
							
						 | 
						
							
								  | 
								
									
									«  Ответ #6 : 06-05-2004 20:56 »    | 
								
								 | 
							  
							 
							В gcc есть свой способ указывать выравнивание для полей структур -- атрибут aligned struct my_struct_aligned {     short aligned_field_1;      int aligned_field_2 __attribute__((aligned (8)));    };  Для примера, вот программа для gcc #include <stdio.h>
  #pragma pack(push, 8)  struct my_struct_pack {     short pack_field_1;      int pack_field_2;    };  #pragma pack(pop)
  struct my_struct_aligned {     short aligned_field_1;      int aligned_field_2 __attribute__((aligned (8)));    }; 
  struct my_struct_union {     union      {         short union_1_field_1; /* My data field */          char align_1[8];                /* Alignment 64 bits */      } _u1;           int union_field_2;                       /* This field is aligned to 64 bits */  }; 
  #define union_field_1 _u1.union_1_field_1 int ptr_diff(void * p1, void * p2) {     return (char *)p2 - (char *)p1; }
  int main() {     struct my_struct_aligned sa;     struct my_struct_union su;     struct my_struct_pack sp;
      printf( "pack: %d\n", ptr_diff( &(sp.pack_field_1), &(sp.pack_field_2) ) );     printf( "aligned: %d\n", ptr_diff( &(sa.aligned_field_1), &(sa.aligned_field_2) ) );     printf( "union: %d\n", ptr_diff( &(su.union_field_1), &(su.union_field_2) ) );     return 0; } У меня под gcc 3.3 получается такой вывод: pack: 4 aligned: 8 union: 8 Получается, что gcc игнорирует #pragma pack.  С другой стороны, ms vc обругает gcc-ный атрибут.  Выходит, что использование union -- наиболее переносимый подход из представленных.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 25-11-2007 20:24 от Алексей1153++ »
								 | 
								
									 
									Записан
								 | 
							  
							 
							
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							npak
							
						 | 
						
							
								  | 
								
									
									 « Ответ #7 : 06-05-2004 20:56 »   | 
								
								 | 
							  
							 
							В gcc есть свой способ указывать выравнивание для полей структур -- атрибут aligned struct my_struct_aligned {     short aligned_field_1;      int aligned_field_2 __attribute__((aligned (8)));    };  Для примера, вот программа для gcc #include <stdio.h>
  #pragma pack(push, 8)  struct my_struct_pack {     short pack_field_1;      int pack_field_2;    };  #pragma pack(pop)
  struct my_struct_aligned {     short aligned_field_1;      int aligned_field_2 __attribute__((aligned (8)));    }; 
  struct my_struct_union {     union      {         short union_1_field_1; /* My data field */          char align_1[8];                /* Alignment 64 bits */      } _u1;           int union_field_2;                       /* This field is aligned to 64 bits */  }; 
  #define union_field_1 _u1.union_1_field_1 int ptr_diff(void * p1, void * p2) {     return (char *)p2 - (char *)p1; }
  int main() {     struct my_struct_aligned sa;     struct my_struct_union su;     struct my_struct_pack sp;
      printf( "pack: %d\n", ptr_diff( &(sp.pack_field_1), &(sp.pack_field_2) ) );     printf( "aligned: %d\n", ptr_diff( &(sa.aligned_field_1), &(sa.aligned_field_2) ) );     printf( "union: %d\n", ptr_diff( &(su.union_field_1), &(su.union_field_2) ) );     return 0; } У меня под gcc 3.3 получается такой вывод: pack: 4 aligned: 8 union: 8 Получается, что gcc игнорирует #pragma pack.  С другой стороны, ms vc обругает gcc-ный атрибут.  Выходит, что использование union -- наиболее переносимый подход из представленных.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 25-11-2007 20:34 от Алексей1153++ »
								 | 
								
									 
									Записан
								 | 
							  
							 
							
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							RXL
							
						 | 
						
							
								  | 
								
									
									 « Ответ #8 : 07-05-2004 06:36 »   | 
								
								 | 
							  
							 
							Cамым переносимым методом обычно было #ifdef __WIN32__ ... #else ... #endif 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Mayor
							
								Специалист 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #9 : 19-05-2004 02:01 »   | 
								
								 | 
							  
							 
							Union можно использовать, когда размер структуры известен заранее ,и это действительно удобно в плане переносимости .
  Ища в MSDN aligned я наткнулся на __declspec(align(#)) , описания gcc у меня нет , но судя по смыслу это тоже самое, так что в плане переносимости можно воспользоваться советом RXL . Кстати в плане совместимости, насколько gcc совместим с lcc-win32 ?
  А вот чем заменить pack я не знаю , но пока проблема переносимости не стоит , так что буду использовать в msvc ... 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							1n c0de we trust 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							npak
							
						 | 
						
							
								  | 
								
									
									 « Ответ #10 : 19-05-2004 10:41 »   | 
								
								 | 
							  
							 
							Mayor, ты можешь использовать для выравнивания union макросы #define ADJUST_TO_MULTIPLE(n, base) ((((n) + (base) - 1)/(base))*(base)) #define ALIGN_TO_8(n) (ADJUST_TO_MULTIPLE(n, 8))
  union {     struct some_struct _u1_value1;     unsigned char _u1_align[ALIGN_TO_8(n)]; } u1; для pack в gcc есть атрибут packed. Судя по инфе в интернете, lcc нацелен на строгую поддержку ansi c.  В нём, похоже, не поддерживаются расшиения gcc.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 25-11-2007 20:34 от Алексей1153++ »
								 | 
								
									 
									Записан
								 | 
							  
							 
							
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Mayor
							
								Специалист 
								
								 
								  Offline
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #11 : 21-05-2004 01:41 »   | 
								
								 | 
							  
							 
							Я думаю вариант с union на произвольных структурах несколько сложноват . Зато предложенные вами alig% , pack% и #ifdef удовлетворяют всем требованиям и являются кроссплатформенными . Всем спасибо за помощь , вопрос полностью разрешен   P.S. ну чтож попробую заценить через недельку lcc, все равно я с gcc пока не работаю , таким образом обратная совместимость пока  мне не нужна  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							1n c0de we trust 
						 | 
					 
				 
			 |  
		 
	 | 
	 |