Forum Clubic

Fwrite en C (big or little endian..) dev c++

salut

j’ai un code ci dessous:


fp4=fopen("mssgeoriginal.txt","w+b");//check routine output for comparison.
 fwrite(message,4,14,fp4); 

avec message un tableau de long contenant des constantes (et pas accédé jusque la)


message[0]=0xB5620106;
message[1]=52;

etc…

le hic c que quand je regarde le fichier ecrit, l’ordre des octets pour le long est inversé :
ex:

060162B5

pour la première case par exemple.

je c que c un truc little endian/big endian. :confused:

j’utilise devc++ sous windows pour developper mais je c pas ou je peux régler le paramètre pour que le compilateur me traite mes nombres en little ou big endian (peu importe le principal c qu’il garde cette convention pour toutes les fonctions…)

qqun aurait une idée ou ce trouve ce fameux paramètre ?
(ou alors une autre fontion pour écrire un long en binaire brut dans un fichier)

thanks :slight_smile:

C’est à toi de faire la conversion little <–> big endian AVANT l’écriture dans le fichier.

Vu que ça dépend du processeur, je doute que le compilateur puisse produire un exécutable travaillant en big endian, et fonctionnant sur ta machine (je présume que c’est du Windows, donc x86, dont little endian)

Tu as ntohs/ntohl (network to host short/long) et htons/htonl (host to network short/long) qui te permettent de faire mumuse avec ça.

ok thks :slight_smile:

Ca va mieux de cette façon?

fp4=fopen("mssgeoriginal.txt","w+b");//check routine output for comparison.
fwrite(message,sizeof(char), 4 * 14,fp4); 

enfin bon, je pense pas…

EDIT: Ha ben non, ça marche pas… mais je viens de voir qu’il existe une instruction ASM pour convertire une valeur de big endian en litlle endian (BSWAP).

Ca ne répond pas à son problème :??:
Il faut que, par exemple le chiffre 0xABCD qui est stocké comme 0xDCBA en little endian soit stocké sous la forme original 0xABCD, il faut donc swaper les bits.

Les bytes plutôt? Mais l’instruction X86 BSWAP le fait.

Mais bon comme je suis pas un dieu en assembleur (loin de la) je ne peux pas le faire. Si tu arrives à nous pondre une fonction avec de l’assembleur à l’intérieur qui inverse les bytes d’un entier tout bête :whistle:

Les bytes ou les bits, ça revient au même et effectivement, bswap le fait et c’est ce que j’utilise :wink:
Ca pourrait donner :


mov eax, ma_variable
bswap eax

s’tout con en fait :neutre:

Ha ben ouai en faite je suis bête. J’essayais de faire une fonction de ce type avec de l’assembleur inside:

int LITTLE_TO_BIG_ENDIAN(int);

Mais comment renvoyer une valeur d’une fonction directement en ASM? Avec un RET? Mais comment passer la valeur de retour?


int LEBE_Convert(int value)
{
int return_value;

	_asm
       {
  mov eax, value
  bswap eax
  mov return_value, eax
	}
	return return_value;
}

void write_to_file(const char * outputfile,int value)
{
FILE *fp;

	fp = fopen(outputfile,"wb");
	if (!fp)
  return;
	fwrite(&value,1,sizeof(value),fp);
	fclose(fp);
}

int main(int argc, char *argv[])
{
int value;
int ret_value;
       
	ret_value = 0;
	value = 0x44332211; 

        printf("value %d\n", value);
	write_to_file("little_endian.txt",value);

	ret_value = LEBE_Convert(value);
        printf("retvalue %d\n", ret_value);
	write_to_file("big_endian.txt",ret_value);

        return 0;
}

Ils ont vraiment été coller de l’assembleur dans ce basar…

Encore heureux que t’es sous Win (x86, x64 au pire) hein :slight_smile:

Boah disons que j’ai un peu de mal avec la syntaxe AT&T bien que j’adore gcc :smiley:

Allez hop, une routine portable :


int LEBE_ConvertGeneric(int value)
{
int return_value;
char a,b,c,d;

	// extrait chaque bits
	a=value&0x000000FF;
	b=(value&0x0000FF00) >> 8;
	c=(value&0x00FF0000) >> 16;
	d=(value&0xFF000000) >> 24;
	return_value = (a << 24) | (b << 16) | (c << 8) | d;
	return return_value;
}

Ben voilà :slight_smile:

Ceci dit, c’est pas plus portable :slight_smile: parce que là, il se passe quoi si le système il code ses octets n’importe comment ? :slight_smile:

(<-- dehors)

Bah je ne suis pas sous windows, mais sous debian… :wink:
et pour le problème des indiens (moi je dit indiens pas endian), la fonction htonl() marche tres bien…

le seul soucis ke j’ai encore, c’est pour connaitre la taille des frames
1 frame = header(4 octets) + Data(??? octets)

donc voila, faut parcourir le fichier et a chaque fois k’on trouve les bits de synchronisation du header on lit le bitrate pour calculer la durée de la frame?

ou y’a un moyen de savoir la taille des data mp3 ??

Le problème du big/little endian n’a rien à voir avec le fait que tu sois sous Windows ou Linux mais sur un cpu x86 ou ppc par exemple.
Pour connaitre la taille de la trame, je lit le fichier jusqu’à trouver la première trame valide, si c’est du CBR, je calcule la taille en utilisant le bitrate et le taux d’échantillonnage, la, vu que je connais la taille de la trame, je seek à la prochaine trame et je la compare avec la trame courante, si elles sont identique, ça rulez, pas besoin de continuer à parser le fichier.
Si c’est en VBR, la faudra tatouiller le header VBR ou VBRi comme je te l’ai indiqué, tout se trouve dedans, tu n’as rien à calculer.
Pour la frame sync, tu DOIS bien checker comme il faut, les 11 bits mais aussi check tous les bits invalides genre si tu as 01 au mpeg_id, c’est pas bon (à toi de voir le degré de tolérance).