6
votes

Tableau TypeCast pour structurer en C

J'ai une structure comme celle-ci xxx pré>

Je reçois un paquet dans un tableau p> xxx pré>

Je veux prendre la SEQNUM, les données Tout séparément.Est le travail de TypeCast suivant. Il donne une valeur indésirable pour moi. P>

struct packet *pkt;
pkt=(struct packet *)buf;
printf(" %d",pkt->seqnum)


5 commentaires

Essayez de lire le bon nombre d'octets: Char Buf [TIZEOFOF (STR SUMPLET)]; et avec: Lire (FD, BUF, TIZEOF (STRUCTURE));


@MARCASSIN: Cela garantit que le nombre d'octets lus est égal à la taille de la structure, mais cela ne change pas les octets entrants et ne fait donc rien pour s'assurer qu'ils ont un rembourrage ou une endansion qui correspond à la structure. Si les octets entrants ne possèdent pas trois octets entre le type type [1] et le temps float1 mais la structure fait, alors que lue est complètement cassé.


Pour des raisons de beauté, ne tapez jamais le s'il vous plaît aidez-moi avec le code. phrase à nouveau


Voulez-vous une solution qui fonctionne dans Standard c ou souhaitez-vous une solution pour une implémentation C spécifique C? Quelle mise en œuvre (y compris quelle plate-forme cible)?


@ Eric Postpischil J'exécute ceci à l'aide du compilateur GCC à Ubuntu


3 Réponses :


8
votes

Non, cela ne fonctionnera probablement pas et est généralement une mauvaise façon de faire cela.

Vous devez utiliser des extensions spécifiques au compilateur pour vous assurer qu'il n'y a pas de rembourrage invisible entre vos membres de la structure, pour quelque chose comme ça pour travailler. Avec GCC, par exemple, vous l'utilisez à l'aide du __ attribut __ () < / code> Syntaxe.

C'est, donc, pas une idée portable.

Il est bien préférable d'être explicite à ce sujet et de déballer chaque champ. Cela vous donne également une chance d'avoir une endiangness définie dans votre protocole de réseau, ce qui est généralement une bonne idée de l'intérêt de l'interopérabilité.


1 commentaires

Salut merci. Pouvez-vous indiquer comment déballer chaque champ dans l'exemple ci-dessus.



5
votes

Non, ce n'est généralement pas un code valide. Vous devriez faire la structure d'abord, puis les trucs membrures: xxx

et ainsi de suite.

Vous devez prendre grand soin pour obtenir la tailles de type et l'endansion. < / p>


0 commentaires

2
votes

Tout d'abord, vous ne pouvez pas savoir à l'avance lorsque le compilateur insérera des octets de rembourrage dans votre structure pour l'optimisation des performances (alignement de la ligne de cache, alignement entier, etc.), car il est dépendant de la plate-forme. Sauf bien sûr, si vous envisagez de construire l'application uniquement sur votre plate-forme.

Quoi qu'il en soit, dans votre cas, il semble que vous obtenez des données de quelque part (réseau?) Et il est fort probable que les données ont été compactées ( Pas d'octets de rembourrage entre les champs).

Si vous souhaitez vraiment taper votre matrice à un pointeur de structure, vous pouvez toujours dire au compilateur de supprimer les octets de rembourrage qu'il pourrait ajouter. Notez que cela dépend du compilateur que vous utilisez et n'est pas une mise en œuvre de la norme C. Avec GCC, vous pouvez ajouter cette déclaration à la fin de la définition de votre structure: xxx

Notez que cela affectera les performances de l'accès des membres, etc.

sauf si vous avez une très bonne raison de le faire, n'utilisez jamais l'attribut __ __ ((emballé)) chose!

L'autre solution, ce qui est beaucoup plus conseillé consiste à faire l'analyse par vous-même. Vous venez d'attribuer une structure appropriée et de remplir ses champs en recherchant la bonne information de votre tampon. Une séquence d'instructions memcpy est susceptible de faire le tour ici (voir la réponse de Kerrek)


3 commentaires

Le compilateur spécifique au compilateur __ (code) __ ((((code)) n'est pas standard C, mais sera toujours valide si le même compilateur est utilisé sur plusieurs plates-formes. Au fait, le contexte de l'OP semble impliquer un code associé au réseau et ainsi, les paquets sont emballés d'où la suggestion.


@ERICPOSTPISCHIL J'ai édité ma réponse pour le rendre plus clair. L'attribut __ __ limite la portabilité d'un extrait de code dans le sens où certains compilateurs pourraient ne pas intégrer les attributs requis, mais si le même compilateur est utilisé tout au long de plusieurs plates-formes, existe-t-il une portabilité sur Plateformes ? (Je pose cela de nettoyer mon esprit :))


Si elle est prise en charge, __ attribut __ ((Emballé)) résout le problème du remplissage, mais pas les problèmes d'endansement ou d'autres problèmes sur la manière dont les valeurs sont codées / représentées (par exemple, si le type float Utilise IEEE 754 ou quelle est la taille du type int est). Il existe deux façons de résoudre ce problème: écrire dans la norme C, lisant chaque octet individuellement et convertir en types natifs en utilisant Arithmetic et CETERA, ou écrire pour une implémentation spécifique et une cible avec les octets dans le struct < B> Complètement défini et en fonction de la mise en œuvre.