Disons que j'ai une classe de vecteur: Mais, je voudrais pouvoir y parcourir sans la convertir à un tableau de flotteurs. Bien qu'un casting soit acceptable dans ce cas, je suis curieux de voir si quelque chose le long des lignes de la fonctionnalité C ++ comme une fonctionnalité de C ++ est faisable dans le droit C. Par exemple, en C ++, depuis IE, std :: vecteur
[] code> surchargé surchargé, je peux transmettre l'adresse de son premier index à une fonction de prise d'un
vide * code>. p>
void do_something_with_pointer_to_mem( void* mem )
{
// do stuff
}
int main( void )
{
std::vector< float > v;
// fill v with values here
// pass to do_something_with_pointer_to_mem
do_some_with_pointer_to_mem( &v[ 0 ] );
return;
}
3 Réponses :
Vous n'obtenez pas le sucre syntaxique de C ++, mais il est facile d'écrire la fonction que vous écririez en C ++ comme opérateur [].
for (int i = 0; i < 3; i++) { printf("%f\n", get_vec3(v, i)); }
Serait-il avantageux de le faire statique code>,
en ligne code> ou une combinaison des deux?
statique code> lui donnerait statique, plutôt que dans la portée mondiale (je ne comprends donc pas pourquoi vous pensez que ce serait bien).
Inline code> serait une optimisation potentielle, mais vous auriez besoin de profiler.
Si tous vos champs de structure sont du même type, vous pouvez utiliser un syndicat comme suit: de cette façon, vous pouvez accéder à chaque champ x, y ou z indépendamment ou itérer sur eux en utilisant le tableau Vect3_A. Cette solution n'a rien coûté en mémoire ou en calcul mais nous pouvons être un peu loin d'une solution C ++. P> P>
Ceci est élégant. Souhaitez-vous expliquer exactement comment cela fonctionne, cependant? Je ne me suis jamais vraiment retrouvé à utiliser des syndicats auparavant; Bien que je sache assez bien C ++, je suis toujours assez nouveau à C.
Comportement non défini? "6.2.6.1.7: Lorsqu'une valeur est stockée dans un membre d'un objet de type syndical, les octets de la représentation de l'objet qui ne correspondent pas à ce membre mais correspondent à d'autres membres prennent des valeurs non spécifiées."
En fait, comme indiqué dans le commentaire ci-dessus, cela peut être dépendant du compilateur. Mais Afaik, la plupart des compilateurs feront une cartographie simple entre les octets des différents membres de l'Union. Donc, dans l'exemple ci-dessus Vect3_A [0] Maps sur X, Vect3_A [1] Maps sur Y et Vect3_A [2] Cartes à Z. Ceci est simplement une moyenne syntaxique d'accéder aux données de structure. L'instance GLOBALE VEC3 sera toujours 3 * Taille de taille (flottante). Une autre solution d'itération consiste simplement à utiliser l'incrémentation du pointeur. Par exemple & x + 1 correspondra à et y. Qui est fondamentalement la même chose que d'utiliser un tableau.
J'ai testé cela sur GCC X64 (Linux), si quelqu'un est intéressé à voir le code. C'est assez simple et je n'ai eu aucun problème :). Il n'y a vraiment pas de raison pragmatique de ce code à utiliser en C ++, que ce soit, puisque GLM prend presque soin de tout cela.
Le problème en C avec ce que vous essayez de faire est que vous devez savoir comment passer à travers une structure (c'est-à-dire que vous devez connaître les types). La raison std :: vecteur
C ++ code> concept). Cela dit, cela dit, vous pourriez essayer quelque chose de légèrement différent de ce que vous avez suggéré. Si vous ne souhaitez pas utiliser de tableaux, vous pouvez stocker des types génériques. Cependant, lors de la récupération des données et de l'utiliser, l'utilisateur devra savoir quel type de données il s'attend à s'attendre. Ci-dessous évite les matrices (bien qu'une solution potentiellement plus propre existe dans les utiliser) et a une liste liée à la liste de quelque chose qui vous donne la presque même flexibilité de
std :: vecteur
O (n) code> pour tout (vous pouvez être intelligente et inverser la liste à réaliser, peut-être,
o (1) code> insert, mais ceci est simplement par exemple)
#include <stdio.h>
#include <stdlib.h>
typedef struct _item3_t
{
void *x, *y, *z;
struct _item3_t* next;
} item3_t;
typedef struct
{
item3_t* head;
} vec3_t;
void insert_vec3(vec3_t* vec, void* x, void* y, void* z)
{
item3_t* item = NULL;
item3_t* tmp = NULL;
int i = 0;
if(vec == NULL)
return;
item = malloc(sizeof(item3_t));
item->x = x;
item->y = y;
item->z = z;
item->next = NULL;
tmp = vec->head;
if(tmp == NULL) { // First element
vec->head = item;
} else {
while(tmp->next != NULL)
tmp = item->next;
tmp->next = item;
}
}
// This is one method which simply relies on the generic method above
void insert_vec3_float(vec3_t* vec, float x, float y, float z)
{
float* xv, *yv, *zv;
if(vec == NULL)
return;
xv = malloc(sizeof(float));
yv = malloc(sizeof(float));
zv = malloc(sizeof(float));
*xv = x;
*yv = y;
*zv = z;
insert_vec3(vec, xv, yv, zv);
}
void init_vec3(vec3_t* vec)
{
if(vec == NULL)
return;
vec->head = NULL;
}
void destroy_vec3(vec3_t* vec)
{
item3_t* item = NULL, *next = NULL;
if(vec == NULL)
return;
item = vec->head;
while(item != NULL) {
next = item->next;
free(item->x);
free(item->y);
free(item->z);
free(item);
item = next;
}
}
item3_t* vec3_get(vec3_t* vec, int idx)
{
int i = 0;
item3_t* item = NULL;
if(vec == NULL)
return NULL;
item = vec->head;
for(i = 0 ; i < idx && item != NULL ; ++i)
item = item->next;
return item;
}
void do_something(item3_t* item)
{
if(item == NULL)
return;
float x = *((float*)item->x);
float y = *((float*)item->y);
float z = *((float*)item->z);
// To do - something? Note, to manipulate the actual
// values in the vector, you need to modify their values
// at their mem addresses
}
int main()
{
vec3_t vector;
init_vec3(&vector);
insert_vec3_float(&vector, 1.2, 2.3, 3.4);
printf("%f %f %f\n", *((float*)vec3_get(&vector, 0)->x), *((float*)vec3_get(&vector, 0)->y), *((float*)vec3_get(&vector, 0)->z));
do_something(vec3_get(&vector, 0));
destroy_vec3(&vector);
return 0;
}
Dupliqué possible de itération sur les mêmes membres de la structure de type en C