Autor Tema: Struct con structs y un sizeof() que me descoloca ...  (Leído 1986 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Struct con structs y un sizeof() que me descoloca ...
« en: 02 de Febrero de 2016, 15:09:52 »
Tengo un pequeño gran problema que ya me está tocando la moral y no le encuentro solución ... veréis:

En una EEPROM externa escribo un registro que debe tener una longitud de 32 bytes exactamente.

Para construir el contenido del registro utilizo un variable en RAM que es implementación de una struct que tiene la siguiente forma:

Código: CSS
  1. static struct tIdentityRecord record_identity;

La struct tIdentityRecord  es esta:

Código: CSS
  1. struct tIdentityRecord{
  2.    char   code[16];
  3.    int8   control;
  4.    int8   rev;
  5.    int16  pin;
  6.    struct tDateTimeShort tStart;
  7.    struct tDateTimeShort tEnd;
  8.    int16  nrec;
  9. };

Como podéis ver este tIdentityRecord  tiene a su vez dos structs de tipo tDateTimeShort  que son así:

Código: CSS
  1. struct tDateTimeShort{
  2.    int8 year;
  3.    int8 mth;
  4.    int8 day;
  5.    int8 hr;
  6.    int8 min;
  7. };

Si hago un sizeof(struct tDateTimeShort) me devuelve 5 bytes de tamaño (como tiene que ser) pero si hago un sizeof(struct tIdentityRecord) me devuelve 34 en lugar de los 32 que yo quiero, deseo y necesito  :? :shock: :?

Y no entiendo porqué me pasa esto.

Estoy compilando con CSS 5.048 y cuando compilaba con versiones anteriores este mismo registro me generaba realmente un registro de sólo 32 bytes, no 34, creo.

El caso es que haciendo uso de esta estructura he escrito el registro y he descubierto que por arte de magia aparecen dos huecos fantasma en la struct tIdentityRecord, uno detrás de cada struct tDateTimeShort, de forma que me ocupan esos dos bytes más de la cuenta ...

La trama bien escrita sería así : ccccccccccccccccORPPtttttTTTTTrr (32 bytes) pero lo que me escribe es ccccccccccccccccORPPttttt_TTTTT_rr (34 bytes) donde los "_" representan los dos huecos esos que os digo  :5]

Y ya no se por donde tirar ¿se os ocurre algo?
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Struct con structs y un sizeof() que me descoloca ...
« Respuesta #1 en: 02 de Febrero de 2016, 15:41:07 »
Micro de 16 bits ? o 32 bits ?

Pregunto por alguna locura de alineacion, al ser 5 bytes puede que sea eso.. pero raro que lo ponga antes y no despues. A lo que le llaman "padding".
Es lo unico que se me ocurre. Si es de 8 bits no creo que ocurra esto.

Desconectado fuente

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 571
Re:Struct con structs y un sizeof() que me descoloca ...
« Respuesta #2 en: 02 de Febrero de 2016, 15:41:42 »
Seguramente sea por la forma en la que el compilador alinea la estructura.
Busca por google structure alignment c++ a ver si te da alguna pista.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re:Struct con structs y un sizeof() que me descoloca ...
« Respuesta #3 en: 02 de Febrero de 2016, 15:51:19 »
Micro de 16 bits ? o 32 bits ?

Pregunto por alguna locura de alineacion, al ser 5 bytes puede que sea eso.. pero raro que lo ponga antes y no despues. A lo que le llaman "padding".
Es lo unico que se me ocurre. Si es de 8 bits no creo que ocurra esto.

16 bits, un 24FJ256GA110 ... y lo pone después, cada sub-struct tiene 6 bytes en lugar de los 5 que debería, si lo escribo con YMDHM y lo miro veo YMDHM_ donde _ es 0x00. y en el otro exactamente igual
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re:Struct con structs y un sizeof() que me descoloca ...
« Respuesta #4 en: 02 de Febrero de 2016, 15:52:49 »
Seguramente sea por la forma en la que el compilador alinea la estructura.
Busca por google structure alignment c++ a ver si te da alguna pista.

busco y busco y busco pero no encuentro ninguna explicación ... seguiré a ver si suena la flauta. Gracias fuente
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Struct con structs y un sizeof() que me descoloca ...
« Respuesta #5 en: 02 de Febrero de 2016, 16:02:02 »
Justamente es un "padding" para mantener la alineacion.


Código: [Seleccionar]
+-------+-------+
|     code      |
+-------+-------+
|     code      |
+-------+-------+
|     code      |
+-------+-------+
|     code      |
+-------+-------+
|     code      |
+-------+-------+
|     code      |
+-------+-------+
|     code      |
+-------+-------+
|     code      |
+-------+-------+
| contrl|  rev  |
+-------+-------+
|      pin      |
+-------+-------+
| year1 | mth1  |
+-------+-------+
| day1  | hr1   |
+-------+-------+
| min1  |       |
+-------+-------+
| year2 | mth2  |
+-------+-------+
| day2  | hr2   |
+-------+-------+
| min2  |       |
+-------+-------+
|      nrec     |
+-------+-------+

Esos huecos vacios los hace para mantener la alineacion de 16 bits de las estructuras tStart, tEnd. Es decir, ubicando la memoria termina con tStart y va a comenzar con tEnd, como ve que supera el byte toda esa estructura (recorda que en tu estructura tIdentityRecord estas agregando TODA una estructura y no bytes individualmente), lo alinea a los 16bits, esto ocurre nuevamente cuando se encuentra con nrec, en el que no entra ese byte solo y procede a "paddear" la memoria.

Lo que podes hacer es tratar de ponerlo como packed. Aunque es de GCC supuestamente funciona en CCS segun lei en su foro.

Código: C
  1. struct __atribute__((packed)) tIdentityRecord{
  2.      ....
  3. }

En 8 bits no hay problema, pero por eso pregunte sobre que cantidad de bits tenias, al ver que eran impares.
Aunque la respuesta que dieron en el foro de CCS, esto le respondieron:


Citar
It is relatively new to the compiler, that is why it's not documented yet.

You also have to be careful using it, because addressing a word pointer if it's not word aligned will cause address failure on a 16bit PIC. This should only happen if you manually created a pointer to an individual entry in the structure, which according to many C purists is bad code design.

En el que uses un puntero y sin querer apuntes no alineado a la memoria. PIC24/dsPIC permiten el acceso a memoria en bytes

Resumen:

Si usas pointers para acceder a la estructura : Va a depender del micro exclusivamente ( que pueda hacer accesos indirectos a bytes, el PIC24 lo posee).
Si no usas pointers: Podrias llegar a tener una "recarga" o mas tiempo para sacar el dato, "limpiarlo" para poder leerlo si es que no posee acceso a bytes, pero el PIC24 lo tiene.

Para que quede claro por si las dudas se habla de portabilidad.

PD: Si te sirve de consuelo, hubiera sido peor en 32 bits xD
« Última modificación: 02 de Febrero de 2016, 17:26:59 por KILLERJC »

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re:Struct con structs y un sizeof() que me descoloca ...
« Respuesta #6 en: 02 de Febrero de 2016, 16:29:12 »
Si, tenéis razón, en los micros de 16 bits el "aligment" de las variables es de 16 bits para poder asignar bien los punteros a memoria donde se ubican las variables y mis dos structs tDateTimeShort tienen 5 bytes por lo que si quiero puedo empaquetarlos con el packed pero entonces tengo problemas al acceder a su contenido individual y si no los empaqueto entonces tienen que tener un tamaño multiplo de 16 bits o 4 bytes o 6 bytes pero no 5 bytes ... ufffff

Puedo intentar hacer un tDoubleDateTimeShort que tenga 10 bytes y componerlo .... hummmm .... bueno bien gracias amigos por alumbrarme el camino  :mrgreen:

"Care should be taken by the user when accessing individual elements of a packed struct – creating a pointer to 'b' in 'test' and attempting to dereference that pointer would cause an address fault.  Any attempts to read/write 'b' should be done in context of 'test' so the compiler knows it is packed"
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Struct con structs y un sizeof() que me descoloca ...
« Respuesta #7 en: 02 de Febrero de 2016, 16:39:31 »
"Care should be taken by the user when accessing individual elements of a packed struct – creating a pointer to 'b' in 'test' and attempting to dereference that pointer would cause an address fault.  Any attempts to read/write 'b' should be done in context of 'test' so the compiler knows it is packed"

Entonces quiere decir que se puede lograr crear un puntero, pero unicamente a la estructura principal y no un puntero a sus componentes?. Y acceder a los componentes de la estructura secundaria a traves de la estructura primaria?

Espero que haya sido claro como lo pregunte :P

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re:Struct con structs y un sizeof() que me descoloca ...
« Respuesta #8 en: 02 de Febrero de 2016, 17:00:27 »
"Care should be taken by the user when accessing individual elements of a packed struct – creating a pointer to 'b' in 'test' and attempting to dereference that pointer would cause an address fault.  Any attempts to read/write 'b' should be done in context of 'test' so the compiler knows it is packed"

Entonces quiere decir que se puede lograr crear un puntero, pero unicamente a la estructura principal y no un puntero a sus componentes?. Y acceder a los componentes de la estructura secundaria a traves de la estructura primaria?

Espero que haya sido claro como lo pregunte :P

Si, si, te he entendido perfectamente ... pueeeesss ... no lo se, parece que hay algún tipo de problema y el puntero puede apuntar mal a la dirección de un componente ... habrá que estudiar/investigar más el asunto.

Pero eso ya será para otro día, porque ahora voy a ajustar la estructura principal para que pueda ser ajustada a los 32 bytes que necesito sin que me sobre ni falte ninguno ...

... y ya después miraré en qué condiciones puedo jugar sin problemas con variables que no sean múltiplos/submúltiplos de 16.  :mrgreen:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania