2010-08-28 14 views
6

Tengo un C (no C++) struct que dice asíC matrices struct

typedef struct mystruct{ 
float a,b; 
int x, y; 
} mystruct; 

Luego, en una función que recopilar datos de esta manera:

mystruct List[MAX]; 
ListNumber = 0; 

for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    List[ListNumber].a = masterlist[i].a; 

... etc

ListNumber++; 
} 
} 

luego envío la matriz a una función

DoStuff(static int max, mystruct array[max]){ 
    Stuff 
} 

Esto funciona, pero cuando trato de hacerlo de esta manera ....

mystruct setter(int i) 
{ 
mystruct TEMP; 
TEMP.a = masterlist[i].a; 
//......etc 
return TEMP; 
} 


mystruct List[MAX]; 
ListNumber = 0; 

for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    List[ListNumber] = setter(i); 
    ListNumber++; 
} 
} 

provoca una gran cantidad de errores cobardes. ¿Por qué está pasando esto? editar: @ tommieb75 No puedo dar muchos detalles, los resultados no parecen tener un patrón. La lista se usa como una forma generalizada de dibujar cosas en la pantalla, y tener la función en lugar de la configuración directa crea problemas extraños en la representación (y al azar), pero no produce ningún error del compilador. gdb muestra algunos enteros como más grandes que un entero, ese es el único patrón que encuentro. masterlist es una matriz global de otra estructura. Los datos deben convertirse a la estructura en este ejemplo. Sin advertencias o errores del compilador en absoluto. Puedo entregar avisos más sensibles quizás, pero siempre me informan de cualquier error general que pueda pensar. Voy a probar la solución seleccionada, eso debería ser suficiente. De todos modos, las funciones similares que devuelven las estructuras se usan en mi código y todo funciona perfectamente a excepción de este caso con una matriz de estructuras.

+1

Podría publicar algunos de los errores que está recibiendo? – GameFreak

+0

Alguien actualiza mi memoria: ¿Puedes devolver las estructuras por valor en C? –

+2

¿por qué no? los punteros deberían ser más rápidos, pero podría devolver por valor. Por cierto. www.ideone.com y usted podría verificar ;-) – nilphilus

Respuesta

1

para un ajuste sencillo de un miembro de estructura necesita una copia de todo un elemento de estructura?

mystruct List[MAX]; 
ListNumber = 0; 

for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    List[ListNumber].a = masterlist[i].a; 
    ListNumber++; 
} 
} 

Si realmente necesita una función, utilice el destino-memoria como parámetro como:

void setter(mystruct *dest,const mystruct *src) 
{ 
    dest->a = src->a; 
} 
for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    setter(&List[ListNumber], &masterlist[i]); 
    ListNumber++; 
} 
} 
+0

Sí, la función es limpiar un poco la función, es una monstruosidad masiva difícil de leer y alterar de manera rápida. Sin embargo, esta parece ser una solución interesante, voy a probarla. – Balkania

1

lo que es

mystruct setter(i) 
{ 
mystruct TEMP; 
TEMP.a = masterlist[i].a; 

'i' tiene cualquier tipo?

// Si se producen errores con miembros sin inicializar en estructura que podría ayudar a http://ideone.com/WRLVG

+1

Es implícitamente int. – Potatoswatter

+0

@Potatoswatter argumentos también? Recuerdo acerca de los valores devueltos, pero no los argumentos (de todos modos tienes razón) – nilphilus

0

El primer problema es su definición de la moda no es una firma de la función legal. El parámetro i debe darse un tipo

mystruct setter(int i) { 
    ... 
} 

También utiliza la variable masterlist que no se define en la función. Esto puede declararse legalmente en otro lugar como estático. Si no es así a pesar de que tendrá que ser accesible a la función de alguna manera

+0

Masterlist es un global. No sé el nombre correcto en C, sin embargo ... de todas formas el código que escribí se hizo sobre la marcha, de otro modo hubiera sido demasiado grande. – Balkania

+0

Además, eso no era copiar y pegar código real, simplemente hice un ejemplo sobre la marcha para eliminar todo el ruido que lo rodeaba ... por supuesto, lo real es lo correcto, o mi compilador se quejaría; P – Balkania

+0

@Blakania: Usted No obtendremos ninguna respuesta útil, ya que su ejemplo inventado parece haber dejado fuera el problema real. – caf

0

El problema es que dentro de la función setter usted tiene una pila asignado variables TEMP la que se sale del ámbito una vez que la función devuelve ... que podría ser mejor para asignar el puntero a my_struct en el montón y devolver la dirección de la vuelta a la rutina de llamada ...

Editar:

mystruct *setter(int i){ 
    mystruct *ptr_myStruct; 
    ptr_myStruct = malloc(sizeof(mystruct)); 
    if (ptr_myStruct != NULL){ 
     ptr_myStruct->a = masterlist[i].a 
     // etc... 
     return &ptr_myStruct; 
    } 
    return NULL; 
} 

mystruct List[MAX]; 
ListNumber = 0; 

for(i = 0; i < MAX; i++) 
{ 
if(conditions_meet) 
{ 
    List[ListNumber] = setter(i); 
    ListNumber++; 
} 
} 

Eso es lo que se necesita para obtener los valores de vuelta una vez que la rutina se apaga de alcanceEso se llama retorno por referencia

+0

Lo devuelve por valor. – Potatoswatter

+0

Diferencia entre retorno por valor y retorno por referencia ... que es lo que menciono arriba, devolviendo la dirección al puntero asignado en el montón que devuelve por referencia. – t0mm13b

+0

Si regresara por referencia, habría un problema, pero afortunadamente, C no tiene esa característica. Si el retorno por valor no funcionó, probablemente no le hubieran permitido compilar. – Potatoswatter