[OWNED] Definir l'adresse d'un tableau

Definir l'adresse d'un tableau [OWNED] - C - Programmation

Marsh Posté le 08-01-2005 à 19:22:40    

Hello,
Bon, je sais que c cho à expliquer mais  :D ...
 
 
Je bosse sur un jeu et je dois réaliser la chose suivante:
Sur emulateur, le tableau[] doit être placé en ram (peu importe l'adresse).
Sur console, le tableau[] doir être placé en rom (à une adresse précise).
Pour passer de l'un a l'autre, j'édite qu'une seule ligne de code (et pas toutes les fois où est utilisé le tableau).
 
Donc, dans tout mon programme j'utilise (truc dans le genre):
unsigned char map_data[256]; //Création d'un tableau en ram, à une adresse *inconnue*.
...
map_data[x+y*32]=z;
 
Mais voila, comment faire pour que map_data soit placé a une adresse bien précise??!
 
J'ai pensé faire:
unsigned char *map_dat;
map_dat= (uchar*) 0x01100;
...
map_data[x+y*32]=z;
 
Mais, celà "bouffe" des instructions cpu supplémentaires à chaque utilisation du tableau (addition de deux adresses *variables*).
Alors que dans le premier exemple, le cpu additionne une valeur fixe à une valeur *variable*...
 
Donc, comment faire?
Il y a t'il un moyen du style (au hasard) : "#define address map_data 0x01100" ?
PS: J'utilise GCC (comme compilateur).
 
En GROS GROS GROS :
Je cherche à pouvoir controller l'adresse d'un tableau (qui est normalement crée en RAM, de façon incontrollable) AVANT compilation.
 
 
Merci de vos réponses.
 
A+
 
Fonzie


Message édité par FonzieV le 10-01-2005 à 15:40:35
Reply

Marsh Posté le 08-01-2005 à 19:22:40   

Reply

Marsh Posté le 08-01-2005 à 21:23:32    

FonzieV a écrit :

Hello,
Bon, je sais que c cho à expliquer mais  :D ...
 
Je bosse sur un jeu et je dois réaliser la chose suivante:
Sur emulateur, le tableau[] doit être placé en ram (peu importe l'adresse).
Sur console, le tableau[] doir être placé en rom (à une adresse précise).
Pour passer de l'un a l'autre, j'édite qu'une seule ligne de code (et pas toutes les fois où est utilisé le tableau).


/* global.c */
#include "global.h
 
/* definition externe : -DEMULATION ou rien */
#ifdef EMULATION
static unsigned char map_data_[MAP_DATA_SIZE];
unsigned char *map_data = map_data_;
#else
unsigned char *map_data = (unsigned char *)ADRESSE_EN_DUR;
#endif


On utilise partout 'map_data' comme un tableau
 

/* global.h */
#define MAP_DATA_SIZE 256
extern unsigned char *map_data;


Dans le linker de la cible réelle :
 
reserver 256 octets à partir de l'adresse ADRESSE_EN_DUR


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 08-01-2005 à 22:19:29    

vive les compound literals de C99

Reply

Marsh Posté le 09-01-2005 à 00:25:17    

"/* global.c */
#include "global.h
 
/* definition externe : -DEMULATION ou rien */
#ifdef EMULATION
static unsigned char map_data_[MAP_DATA_SIZE];
unsigned char *map_data = map_data_;
#else
unsigned char *map_data = (unsigned char *)ADRESSE_EN_DUR;
#endif "
 
I see...
Par contre, faut pas que je me plante car c'est ce tableau la clef du "game engine" (au niveau de l'optimisation, c'est super hot)...
 
Donc tu me confirme que, au niveaux des instructions que ça va générer en asm, que :
j=tableauclassique[i];
est aussi rapide que (avec map_data comme tu l'as défini):
j=map_data[i];
?
 
Merci bcp.
-------------------------------------
Sinon, g testé le "tips":
 
static uchar dynamic_map[64*64*4];
uchar *ref_dynamic_map=dynamic_map;
 
ensuite, j'ai ça (dans les autres pages ou j'utilise le tableau)
extern uchar *ref_dynamic_map[];  
 
et quand je fait ref_dynamic_map[quelquechose]
j'obtient ça:
Error : "array subscript is not an integer"
bref, c zarb.
 
 
 
 
A+
 
Fonzie


Message édité par FonzieV le 09-01-2005 à 00:48:59
Reply

Marsh Posté le 09-01-2005 à 16:55:28    

Si tu déclares ton tableau avec "uchar *ref_dynamic_map" d'un coté, faut pas le déclater avec "extern uchar *ref_dynamic_map[]" de l'autre... Enlève les [].

Reply

Marsh Posté le 09-01-2005 à 23:03:15    

Merci bcp, ça marche nickel.
;) Bon et puis pour l'histoire de l'optimisation je laisse tomber, le 68K @ 8Mhz, c de la balle !

Reply

Marsh Posté le 10-01-2005 à 10:08:54    

Je te confirme que l'accès aux éléments de ton tableau est aussi rapide pour les deux manières de le déclarer :
- unsigned char tab[N];
- unsigned char *tab;
Le compilateur va, dans les deux cas effectuer les mêmes opérations lors des accès. En fait, en dehors de l'allocation de mémoire, les deux écritures sont "équivalentes", la seule chose que tu ne peux pas faire avec un tableau c'est déplacer son adresse de départ (unsigned char tab[N]; ..... tab++). Du reste, si tu lui affectes une valeur dès la déclaration, ce serait une bonne idée de déclarer ton pointeur avec "const" : unsigned char * const tab = ADRESS;
Au cas où tu en aurais besoin, voici les 2 écritures pour un tableau à 2 dimensions :
- unsigned char tab[N][10];
- unsigned char (*tab)[10];  //() pour priorité entre * et []

Reply

Marsh Posté le 10-01-2005 à 15:13:35    

Ok, merci à tous.
lsdyoyo, c exactement la réponse que j'attendais quand je parlais des cycles cpus, en plus avec "const", c encore plus classe (il faut souvent ajouter ce genre d'infos quand on compile au niveau maximum d'optimisation avec GCC, cf : "volatile" ).
 
Pour les tableaux a 2 dims, c bon a savoir mais je préfere controller toutes les multiplications moi-même (pour pouvoir faire des << et >> à la place)... Enfin, je me comprends LOL.
 
Merci bcp.
 
++
 
Fonzie

Reply

Marsh Posté le 11-01-2005 à 11:46:40    

Deux remarques :
- const me modifie en rien le code généré (contrairement à "volatile" ). Ca permet d'obtenir des erreurs à la compilation si le source veut modifier une variable "const".
- A moins que tu ne descendes jusqu'au niveau de l'assembleur, les compilos s'en sortent bien souvent mieux que toi pour optimiser les accès aux structures ou tableaux. Il existe, notamment sur processeur Intel, des modes d'adressages spécialisés pour les tableaux d'éléments de taille 2, 4 et 8. Je pense aussi que la majorité des compilos sont suffisamment optimisés pour employer un décalage de bits plutôt qu'une multiplication si la variable est "unsigned". Dans un source, "x * 32" est plus lisible que "x << 5".

Reply

Marsh Posté le 11-01-2005 à 11:56:53    

En parlant d'optimisation, y'a pas moyen d'optimiser lorsque l'on parcourt un tableau à deux dimensions par les colonnes ?? (pour que le cache serve à qqchose)


Message édité par fafounet le 11-01-2005 à 11:57:29
Reply

Marsh Posté le 11-01-2005 à 11:56:53   

Reply

Marsh Posté le 11-01-2005 à 13:47:10    

lsdyoyo a écrit :

Deux remarques :
- const me modifie en rien le code généré (contrairement à "volatile" ). Ca permet d'obtenir des erreurs à la compilation si le source veut modifier une variable "const".


Ca dépend, de l'implémentation, mais 'const' peut avoir une influence importante sur la taille du code généré et l'empreinte mémoire.  
 
Par exemple :  

static int a[] = {1, 2, 3, 4};


génère  

  • Une réservation mémoire (RAM) de 4 int
  • Une zone d'initialisation dans le code (PROM, Flash, RAM en lecture seule) de 4 int.


[format Motorola, int 32-bit]

00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04


  • un code de recopie de cette zone dans la zone mémoire au démarrage.


alors que

static const int a[] = {1, 2, 3, 4};


génère :  

  • Une zone d'initialisation dans le code de 4 int

et c'est tout.
 
En embarqué, ça peut avoir son importance...


Message édité par Emmanuel Delahaye le 11-01-2005 à 13:50:40

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 11-01-2005 à 15:55:14    

pas qu'en embarqué.

Reply

Marsh Posté le 11-01-2005 à 15:57:45    

Emmanuel Delahaye a écrit :

static int a[] = {1, 2, 3, 4};

génère  

  • Une réservation mémoire (RAM) de 4 int
  • Une zone d'initialisation dans le code (PROM, Flash, RAM en lecture seule) de 4 int.
  • un code de recopie de cette zone dans la zone mémoire au démarrage.

Je suis surpris. Tu es sûr qu'un compilo va générer ET une allocation fixe ET un code de recopie alors que le tableau est déclaré en "static" ?!
Pour un tableau local (auto) du style "int a[] = { 1, 2 };" ok, mais en "static"... Et comment ça se passe en global, le compilo génère N appels à N recopies de bloc avant l'appel de main() ? Hummm... c'est lourd et je ne vois pas l'intérêt.


Message édité par lsdYoYo le 11-01-2005 à 15:59:02
Reply

Marsh Posté le 11-01-2005 à 17:41:36    

lsdyoyo a écrit :

Je suis surpris. Tu es sûr qu'un compilo va générer ET une allocation fixe ET un code de recopie alors que le tableau est déclaré en "static" ?!
Pour un tableau local (auto) du style "int a[] = { 1, 2 };" ok, mais en "static"... Et comment ça se passe en global, le compilo génère N appels à N recopies de bloc avant l'appel de main() ? Hummm... c'est lourd et je ne vois pas l'intérêt.


J'ai constaté ça sur plusieurs plateformes embarquées (Mentor Graphics ex-MRI, notamment).
Comme je l'ai dit, ça dépend de l'implémentation. Je préfère écrire du code qui sera optimisé au mieux.


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 11-01-2005 à 21:08:55    

"Je suis surpris. Tu es sûr qu'un compilo va générer ET une allocation fixe ET un code de recopie alors que le tableau est déclaré en "static" ?!"
Oui c'est logique de toute façon.
 
"En embarqué, ça peut avoir son importance..."
Effectivement, j'ai 64Ko de workram et 256ko de program ram.
Donc ça fait une sacré dif d'avoir un tableau de 32Ko "en double".
 
 
Btw: j'utilise "volatile" comme une sorte d'information pour le compilateur.
Je travail avec des fifo's et gcc n'aime pas trop les écritures multiples genre "for(i=0;i<300;i++){*pw=56;}", il a tendance à supprimer des bout de code pour optimiser si on ne précise pas "volatile" pour les pointeurs de la fifo.


Message édité par FonzieV le 11-01-2005 à 21:09:53
Reply

Marsh Posté le 11-01-2005 à 22:49:11    

Tu dois preciser volatile parce que tes pointeurs sont volatiles. Si ton pointeur n'est pas modifie de maniere asynchrone (par un autre thread par exemple), pas besoin de volatile.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed