Discussion:
Problema con un cast
(demasiado antiguo para responder)
Eduardo
2006-09-04 13:45:25 UTC
Permalink
Tengo el siguiente problema:

Debo llenar una estructura con formato arbitrario, los datos a llenar
estan como texto en un fichero y el tipo (float,int o char) se en un
string aparte.
Voy leyendo el tipo de dato en el string y selecciono la funciones
GetXXX() para que me devuelva el valor correspondiente (si era un
string, un puntero), pongo el valor en la estructura e incremento el
puntero con el valor correspondientre al tipo de dato.

Pos bien, no me sale ni a palos el cast (sin mentir el tipo)
Alguno tendria la gentileza de decirme deberia ser?


Este es un pedazo de codigo que tal vez se explique mejor

//--------------------------------------------------

void *Funciones ;

int GetInt(void);
float GetFloat(void);
char *GetString(void);

void Ini_Struct(void *var , char *key , char *datatype ){
char *dtype;
//............
//............
dtype = datatype;

do{
switch(*dtype){
case 'i': *(int*)var = GetInt() ;
((int*)var)++;
dtype++; break ;
case 'f': *(float*)var = GetFloat() ;
((float*)var)++;
dtype++; break ;

case 's': ????????? var = GetString() ;
(????? var)++;
dtype++; break ;

//..................
}
} while(Go2NextArg());
//...........
}


void main(void){

//....................

Ini_Struct(&Funciones , "Funciones" , "siff" );

//....................
}
//--------------------------------------------------
Zara
2006-09-04 14:35:34 UTC
Permalink
<...>
Post by Eduardo
void *Funciones ;
int GetInt(void);
float GetFloat(void);
char *GetString(void);
void Ini_Struct(void *var , char *key , char *datatype ){
<...>
Post by Eduardo
case 's': ????????? var = GetString() ;
(????? var)++;
// probablemente
var+=strlen(var)+1;
Post by Eduardo
dtype++; break ;
<...>

Zara
Eduardo
2006-09-04 16:02:08 UTC
Permalink
Post by Zara
<...>
Post by Eduardo
void *Funciones ;
int GetInt(void);
float GetFloat(void);
char *GetString(void);
void Ini_Struct(void *var , char *key , char *datatype ){
<...>
Post by Eduardo
case 's': ????????? var = GetString() ;
(????? var)++;
// probablemente
var+=strlen(var)+1;
Post by Eduardo
dtype++; break ;
<...>
Zara
Gracias por responder, pero no trabaja asi.
GetString devuelve un puntero (16 bit), var debe forzarse a puntero a
puntero.
*var debe incrementarse en 2 para tipo int o char* y en 4 para float.

La claridad no es mi fuerte.

Eduardo.
Eduardo
2006-09-04 16:22:12 UTC
Permalink
Si miento con el tipo de variable la asignacion se hace correctamente,
la inquietud es como escribirlo 'legalmente'

*(int*)var = (int)GetString() ;
((int*)var)++ ;


O bien:

*((int*)var)++ = (int)GetString() ;


Eduardo.
Zara
2006-09-05 06:28:51 UTC
Permalink
Post by Eduardo
Post by Zara
<...>
Post by Eduardo
void *Funciones ;
int GetInt(void);
float GetFloat(void);
char *GetString(void);
void Ini_Struct(void *var , char *key , char *datatype ){
<...>
Post by Eduardo
case 's': ????????? var = GetString() ;
(????? var)++;
// probablemente
var+=strlen(var)+1;
Post by Eduardo
dtype++; break ;
<...>
Zara
Gracias por responder, pero no trabaja asi.
GetString devuelve un puntero (16 bit), var debe forzarse a puntero a
puntero.
*var debe incrementarse en 2 para tipo int o char* y en 4 para float.
La claridad no es mi fuerte.
entonces, es simple:

case 'i': *(int*)var = GetInt() ;
var+=sizeof(int);
dtype++; break ;
case 'f': *(float*)var = GetFloat() ;
var+=sizeof(float);
dtype++; break ;

case 's': ????????? var = GetString() ;
var+=sizeof(char *);
dtype++; break ;

Así queda todo bastante congruente. pero cuidado!! por lo que dices,
sizeof(int) debe ser 2 y sizeof(float) debe ser 4. Si no fuese así, ni
el código original ni el código que propongo funcionaría correctamente

saludos,

Zara
Eduardo
2006-09-06 02:17:03 UTC
Permalink
Post by Eduardo
........
case 'i': *(int*)var = GetInt() ;
var+=sizeof(int);
dtype++; break ;
case 'f': *(float*)var = GetFloat() ;
var+=sizeof(float);
dtype++; break ;
case 's': ????????? var = GetString() ;
var+=sizeof(char *);
dtype++; break ;
Así queda todo bastante congruente. pero cuidado!! por lo que dices,
sizeof(int) debe ser 2 y sizeof(float) debe ser 4. Si no fuese así, ni
el código original ni el código que propongo funcionaría correctamente
Muchas gracias! :-)

Eduardo.
Zara
2006-09-11 06:22:49 UTC
Permalink
On Tue, 05 Sep 2006 08:28:51 +0200, Zara <***@terra.es> wrote:

<...>
Post by Eduardo
case 'i': *(int*)var = GetInt() ;
var+=sizeof(int);
dtype++; break ;
case 'f': *(float*)var = GetFloat() ;
var+=sizeof(float);
dtype++; break ;
case 's': ????????? var = GetString() ;
case 's': *(char **) var = GetString() ;
Post by Eduardo
var+=sizeof(char *);
dtype++; break ;
Si es que la falta de cafeíina hace auténticos estragos.

Zara

Zara
2006-09-04 14:35:48 UTC
Permalink
<...>
Post by Eduardo
void *Funciones ;
int GetInt(void);
float GetFloat(void);
char *GetString(void);
void Ini_Struct(void *var , char *key , char *datatype ){
<...>
Post by Eduardo
case 's': ????????? var = GetString() ;
(????? var)++;
// probablemente
var+=strlen(var)+1;
Post by Eduardo
dtype++; break ;
<...>

Zara
Javier M Mora (jamarier)
2006-09-08 00:27:55 UTC
Permalink
Post by Eduardo
Debo llenar una estructura con formato arbitrario, los datos a llenar
estan como texto en un fichero y el tipo (float,int o char) se en un
string aparte.
Voy leyendo el tipo de dato en el string y selecciono la funciones
GetXXX() para que me devuelva el valor correspondiente (si era un
string, un puntero), pongo el valor en la estructura e incremento el
puntero con el valor correspondientre al tipo de dato.
Pos bien, no me sale ni a palos el cast (sin mentir el tipo)
Alguno tendria la gentileza de decirme deberia ser?
Este es un pedazo de codigo que tal vez se explique mejor
//--------------------------------------------------
void *Funciones ;
int GetInt(void);
float GetFloat(void);
char *GetString(void);
void Ini_Struct(void *var , char *key , char *datatype ){
char *dtype;
//............
//............
dtype = datatype;
do{
switch(*dtype){
case 'i': *(int*)var = GetInt() ;
((int*)var)++;
dtype++; break ;
case 'f': *(float*)var = GetFloat() ;
((float*)var)++;
dtype++; break ;
case 's': ????????? var = GetString() ;
(????? var)++;
dtype++; break ;
//..................
}
} while(Go2NextArg());
//...........
}
La confusión está en que una cadena es un array de caracteres. Pero la
lógica es la misma (solo tienes que crear un nuevo tipo de variable):

typedef char *cadena;
...

case 'f': *(float*)var = GetFloat() ;
((float*)var)++;
dtype++; break ;

case 's': *(cadena*)var = GetString() ;
((cadena*) var)++;
dtype++; break ;

En el caso del float, estás almacenando el float dentro de var. En el
caso de la cadena, sólo almacenas el puntero que apunta a la cadena que
está en otra parte. ¿dónde? (si no se tiene claro es causa de errores).

Si lo que se pretende es hacer una serialización (volcar una serie de
variables en un solo array o en un fichero), las cadenas se quedarían
fuera. Yo abogaría por usar strcpy:

case 's': cadena temp = GetString();
strcpy((cadena) var,temp);
(cadena) var += strlen(temp)+1;
dtype++; break;

obviamente habría que asegurarse que var es suficientemente grande para
albergar las cadenas íntegras.

atte. javier m mora

Pd. no he probado el código. Puede tener algún error.
Eduardo
2006-09-08 16:21:06 UTC
Permalink
Post by Javier M Mora (jamarier)
La confusión está en que una cadena es un array de caracteres. Pero la
typedef char *cadena;
...
case 'f': *(float*)var = GetFloat() ;
((float*)var)++;
dtype++; break ;
case 's': *(cadena*)var = GetString() ;
((cadena*) var)++;
dtype++; break ;
En el caso del float, estás almacenando el float dentro de var. En el
caso de la cadena, sólo almacenas el puntero que apunta a la cadena que
está en otra parte. ¿dónde? (si no se tiene claro es causa de errores).
Solo debo guardar el puntero a la cadena, del lugar donde se guarda se
encarga GetString().

GetString() arma la cadena asciiz y la guarda en un buffer, solo
devuelve el puntero.

Me canse de probar y no me sale el cast 'legal' para guardar el puntero
en la estructura.
Mintiendo el tipo devuelto por GetString() funciona
*(int*)var = (int)GetString() ;
Pero me queda la duda de como debe ser.


Eduardo.
Post by Javier M Mora (jamarier)
Si lo que se pretende es hacer una serialización (volcar una serie de
variables en un solo array o en un fichero), las cadenas se quedarían
case 's': cadena temp = GetString();
strcpy((cadena) var,temp);
(cadena) var += strlen(temp)+1;
dtype++; break;
obviamente habría que asegurarse que var es suficientemente grande para
albergar las cadenas íntegras.
atte. javier m mora
Pd. no he probado el código. Puede tener algún error.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
iD8DBQFFALWspRHCj3lPPYMRAuW5AKCigtGJi45nsdno+eI4nxj2neK7wACfaWZW
8yEro+VM1rKFXwLuLpsCAEQ=
=0JN4
-----END PGP SIGNATURE-----
Javier M Mora (jamarier)
2006-09-08 19:17:02 UTC
Permalink
Post by Eduardo
Post by Javier M Mora (jamarier)
La confusión está en que una cadena es un array de caracteres. Pero la
typedef char *cadena;
...
case 's': *(cadena*)var = GetString() ;
((cadena*) var)++;
dtype++; break ;
Solo debo guardar el puntero a la cadena, del lugar donde se guarda se
encarga GetString().
GetString() arma la cadena asciiz y la guarda en un buffer, solo
devuelve el puntero.
Me canse de probar y no me sale el cast 'legal' para guardar el puntero
en la estructura.
Mintiendo el tipo devuelto por GetString() funciona
*(int*)var = (int)GetString() ;
Pero me queda la duda de como debe ser.
Hacer trampas de este estilo, solo te engaña a tí :-) ¿cual es el tamaño
de un puntero? ¿y de un int? ¿16 bytes, 32? esto es una fuente de
problemas elevada. (como ejemplo que se copie solo parcialmente el
puntero)

Y a riesgo de ser pesado, te lo dije ya, puedes crear un nuevo tipo y
usar el puntero al tipo indicado. (eso está arriba).

La otra opción es hacerlo sin declarar nuevo tipo (recuerda que los
punteros tambien son tipos de variables y puedes sacar punteros a ellos:

case 's': *(char**)var = (char*)GetString() ;
((char**) var)++;
dtype++; break ;

char ** es un puntero que apunta a un puntero a char osea un puntero que
apunta al inicio de una cadena.

atte. javier m mora
Eduardo
2006-09-09 23:52:18 UTC
Permalink
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
...........................
Hacer trampas de este estilo, solo te engaña a tí :-) ¿cual es el tamaño
de un puntero? ¿y de un int? ¿16 bytes, 32? esto es una fuente de
problemas elevada. (como ejemplo que se copie solo parcialmente el
puntero)
Totalmente de acuerdo, como en mi caso particular eran los dos de 16
bits 'funcionaba', pero sabia que no era correcto.
Y a riesgo de ser pesado, te lo dije ya, puedes crear un nuevo tipo y
usar el puntero al tipo indicado. (eso está arriba).
No, para nada... y te lo agradezco.
La otra opción es hacerlo sin declarar nuevo tipo (recuerda que los
case 's': *(char**)var = (char*)GetString() ;
((char**) var)++;
dtype++; break ;
char ** es un puntero que apunta a un puntero a char osea un puntero que
apunta al inicio de una cadena.
Eso era lo que me estaba enloqueciendo, probe pilas de formas menos esa
*(char**) :-(


Muchas gracias por la paciencia!


Eduardo.
atte. javier m mora
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
iD8DBQFFAb5KpRHCj3lPPYMRApLNAKCvmo0U23G4cDh4hIK1R5Kiv5fhdACeMEv0
DrLU83uBz9RkP1pbY7WF3OM=
=diYj
-----END PGP SIGNATURE-----
Loading...