No debo de estar en mi sano juicio, pero estoy convencido de que la salida del programa deberia ser "14 14", y sin embargo es "14 16". ¿Alguien me explica donde esta el truco, por favor? Llevo muchisimo tiempo para encontrar que lo que me falla es el sizeof, pero no se por que falla, ¿donde pierdo 2 bytes?
typedef short int WORD;
typedef long int DWORD;
// Cabecera archivo BMP
typedef struct {
WORD bfType; // Debe ser "BM"
DWORD bfSize; // Tam fichero en bytes
WORD bfReserved1; // Debe ser 0
WORD bfReserved2; // Debe ser 0
DWORD bfOffBits; // Offset inicio de datos (def 1078)
} bmpFileHeader;
int main (void);
int main(void) {
bmpFileHeader cabFile;
printf("%d\n", sizeof(cabFile.bfType)+
sizeof(cabFile.bfSize)+
sizeof(cabFile.bfReserved1)+
sizeof(cabFile.bfReserved2)+
sizeof(cabFile.bfOffBits));
printf("%d\n", sizeof(bmpFileHeader));
return 0;
}
La estructura está alineada en regiones de 32 bits(4 bytes), de ahí que pierdas 2 bytes por el final (16bytes es múltiplo de 4 mientras que 14 no).
Internamente los DWORD's están alineados a 32bits por defecto. Si el compilador pusiese las variables en memoria una detrás de otra, el último DWORD estaría desalineado. La alineación permite al procesador leer/escribir las palabras más rápido que si no lo estuviesen.
Edit: Cutre-esquema, habia puesto una tabla en ascii pero se ve mal.. buscaré una imagen de algun lado.
Ahhhhm menos mal que has editado porque ya tenia preparada la siguiente, jasjajs ya que al hacer
void loadbmp_24bpp(char *filen){
bmpFileHeader cabFile;
bmpFileHeader cabFile2;
bmpInfoHeader cabInfo;
FILE *fd;
int sizeOfReal = sizeof(cabFile.bfType)+sizeof(cabFile.bfSize)+sizeof(cabFile.bfReserved1)+sizeof(cabFile.bfReserved2)+sizeof(cabFile.bfOffBits);
// Abrir el fichero
if ((fd = fopen(filen,"rb")) == NULL) {
printf("Error al abrir el archivo '%s'\n",filen);
return;
}
// Cargar cabecera de fichero
fread(&cabFile.bfType, sizeof(cabFile.bfType), 1, fd);
fread(&cabFile.bfSize, sizeof(cabFile.bfSize), 1, fd);
fread(&cabFile.bfReserved1, sizeof(cabFile.bfReserved1), 1, fd);
fread(&cabFile.bfReserved2, sizeof(cabFile.bfReserved2), 1, fd);
fread(&cabFile.bfOffBits, sizeof(cabFile.bfOffBits), 1, fd);
printf("*********\n%d (%d)\n%ld (%d)\n%d (%d)\n%d (%d)\n%ld (%d)\n*********\n",
cabFile.bfType, sizeof(cabFile.bfType),
cabFile.bfSize, sizeof(cabFile.bfSize),
cabFile.bfReserved1, sizeof(cabFile.bfReserved1),
cabFile.bfReserved2, sizeof(cabFile.bfReserved2),
cabFile.bfOffBits, sizeof(cabFile.bfOffBits)
);
// Carga erroneo!!
fseek(fd,0, SEEK_SET);
fread(&cabFile2, sizeOfReal, 1, fd);
printf("*********\n%d (%d)\n%ld (%d)\n%d (%d)\n%d (%d)\n%ld (%d)\n*********\n",
cabFile2.bfType, sizeof(cabFile2.bfType),
cabFile2.bfSize, sizeof(cabFile2.bfSize),
cabFile2.bfReserved1, sizeof(cabFile2.bfReserved1),
cabFile2.bfReserved2, sizeof(cabFile2.bfReserved2),
cabFile2.bfOffBits, sizeof(cabFile2.bfOffBits)
);
return 0;
}
Me salia mal el cabfile2 claramente.
Con "el editado" ha quedado tan claro como la falta que tengo de compiladores XDD
Gracias por la explicacion.
EDIT: No hace falta, el cutre-esquema era grandiosamente explicativo.
Gracias, gracias. Todo clarisimo.
Si quieres deshabilitar el alineado en memoria o, mejor dicho, alinear a byte. Puedes probar algo como esto (o similar porque dependerá del compilador):
#pragma pack(1)
También suele haber algún procedimiento para recuperar el índice de alineación anterior (push/pop).
Esta directiva de compilación se suele usar para estructuras en ficheros (donde no hay alineación que valga).
¿Me he explicado bien? (Que estoy dormido)
Cita de: "gdl"Si quieres deshabilitar el alineado en memoria o, mejor dicho, alinear a byte. Puedes probar algo como esto (o similar porque dependerá del compilador):
#pragma pack(1)
También suele haber algún procedimiento para recuperar el índice de alineación anterior (push/pop).
Esta directiva de compilación se suele usar para estructuras en ficheros (donde no hay alineación que valga).
¿Me he explicado bien? (Que estoy dormido)
Uhm si te has explicado. Mas que nada porque ahora entiendo el codigo que habia visto, en el que ponia:
#pragma pack( 1 )
typedef struct {
char Type[2];
unsigned long Size;
long Reserved;
unsigned long OffBits;
unsigned long InfoSize;
long Width;
long Height;
short Planes;
short BitCount;
long Compression;
unsigned long ImageSize;
long Fill[4];
} stBmpHeader;
#pragma pack( 4 )
Gracias por la indicacion.
No me deja editar mis mensajes, ¿por que?, ¿solo se puede editar 1 por hilo?
Solo para decir que ya use:
#pragma pack(1)
// Cabecera archivo BMP
typedef struct {
WORD bfType; // Debe ser "BM"
DWORD bfSize; // Tam fichero en bytes
WORD bfReserved1; // Debe ser 0
WORD bfReserved2; // Debe ser 0
DWORD bfOffBits; // Offset inicio de datos (def 1078)
} bmpFileHeader;
// Cabecera informacion BMP
typedef struct {
...
} bmpInfoHeader;
#pragma pack(4)
y ya pude poner bien
// Cargar cabecera de fichero
fread(&cabFile, sizeof(bmpFileHeader), 1, fd);
Ademas me funciona tanto para windows como para linux.
Asi pues, gracias por los coments.
Edit: Uhm, este si le puedo editar. No entiendo. ¿Sera por tiempo?
Mejor podrías utilizar lo que te ha dicho gdl para poder recuperar la alineación anterior:
#pragma pack(push, 1)
struct foo {
....
....
};
#pragma pack(pop)
Y cuando haces pop ya no hay stop :lol:
Saludos.
Cita de: "BeRSeRKeR"Mejor podrías utilizar lo que te ha dicho gdl para poder recuperar la alineación anterior:
#pragma pack(push, 1)
struct foo {
....
};
#pragma pack(pop)
Y cuando haces pop ya no hay stop :lol:
Saludos.
Ok, no sabia bien como poner push y pop (por "También suele haber algún procedimiento..").
Luego lo pruebo.
Gracias.
----------------------------
EDIT:
Oppsss.
s@s:~$ gcc *.c -o run
In file included from bmplib.c:1:
bmplib.h:7: warning: malformed `#pragma pack'
bmplib.h:31: warning: malformed `#pragma pack'
In file included from conversionS.c:1:
bmplib.h:7: warning: malformed `#pragma pack'
bmplib.h:31: warning: malformed `#pragma pack'
s@s:~$ gcc --version
2.95.4
s@s:~$ ./run imagen24.bmp sal.bmp
BPP no valido (0 / 24)
Brr, me temo que no me sirve. En win va bien. Pero necesito que tire en linux.