2010-10-15 23 views
2

J'essaye d'imprimer la valeur pointée par une adresse mais le problème est que je dois déréférencer ce pointeur basé sur la taille qui est passée à moi. Donc quelque chose de ce genre:Comment puis-je déréférencer en fonction de la taille?

void print(Address addr, Int size) { 
... 
} 

Je suis un peu confus sur la façon d'y parvenir. Quelqu'un peut me diriger dans la bonne direction?

EDIT: Ok donc je pense:

char p[80]; 
memset(p, '\0', 80); 
memcpy(p, addr, size); 

Et puis déréférencement comme * p. S'il y a un meilleur moyen ou un moyen correct, s'il vous plaît faites le moi savoir

+0

Pouvez-vous élaborer un peu - voulez-vous dire que parfois vous voulez déréférencer le pointeur comme un int de 32 bits (disons si size == 4) et parfois comme un int de 64 bits (if size == 8)? Ou êtes-vous après quelque chose d'autre? –

+0

@Michael: C'est vrai. J'essaie d'imprimer la représentation hexadécimale de ces nombres. – Legend

Répondre

3

Votre question est très floue. Si vous voulez dire que vous voulez vider les données binaires arbitraires de l'adresse passée, vous voulez quelque chose comme:

void print(const unsigned char *addr, size_t size) 
{ 
    while (size--) printf("%.2x", *addr++); 
} 

Ou si vous voulez dire que vous voulez imprimer des données de caractères qui est non nul terminé, essayez:

void print(const char *addr, int size) 
{ 
    printf("%.*s", size, addr); 
} 
+1

J'ai ajouté les qualificatifs const aux arguments 'char *'. Puisque les fonctions ne modifient pas (et ne devraient pas) les cibles des arguments pointeurs, nous pouvons laisser l'optimiseur et la vérification d'erreurs du compilateur en savoir un peu plus sur ce qui se passe à l'intérieur. –

+0

Merci pour le correctif. –

0

S'il est un certain nombre, que je suppose qu'il est, vous aurez besoin de quelque chose comme ceci:

int n=0; 
if (size>sizeof(int)) { return; //int is too small }; 
for (int i=0;i<size;i++) { 
    ((char*)(&n))[sizeof(int)-(i+1)] = ((char*)addr)[size-(i+1)]; 
} 
printf("%d",n); 
+0

Ce code a au mieux un comportement défini par l'implémentation, et plus probablement un comportement indéfini ... –

+0

le fait vraiment, pourquoi? –

+1

Si 'size' est inférieur à' sizeof (int) ', une partie de la représentation de' n' reste non initialisée. Aussi, que vous deviez copier au début ou à la fin est défini par l'implémentation (dépendant de l'endian). –

0

vous pouvez utiliser une instruction switch dans la routine:

switch (size) { 
    case 1: print(*(char*)pointer); break; 
    case 2: print(*(short*)pointer); break; 
    case 4: print(*(long *)pointer); break; 
    case 8: print(*(__int64*)pointer); break; 
    default: puts("unsupported); 
} 

("print" est une routine d'imprimer des entiers de différentes tailles, peut-être en C++ Polymorphism)

Une solution sophistiquée est d'utiliser un modèle C++ par exemple en utilisant un type de paramètre Integer qui est substitué par le type de variable réel lors de l'invocation. Cette routine peut alors agir sur la taille de cette variable Integer (qui peut varier de 1 à 8, ou plus si vous implémentez des entiers plus longs). Cet inconvénient de cette approche est que le compilateur génère une instance de routine pour chaque type d'argument, et une logique dépendant de la taille conduira à des conditions "toujours vraies" pour certains tests. Une solution facile est d'utiliser toujours le type d'entier le plus long que vous attendiez.

+0

Le PO a étiqueté cela comme C non C++ donc je suppose que cela exclut le polymorphisme ou l'impression de surcharge - mais le principal derrière votre réponse est OK. – Andrew