Discussion:
Correcta sintaxis para incrementar un puntero
(demasiado antiguo para responder)
Eduardo
2005-01-05 21:35:35 UTC
Permalink
Hola al grupo!
Soy una persona con conocimientos algo rudimentarios de C , me ha surgido
este problema y no encuentro la manera 'limpia y elegante' de escribir la
instruccion.

Tengo una serie de datos en memoria de longitud y tipo variables, y un
puntero al comienzo.
La estructura es la siguiente:
char TipoDeObjeto[7]
int LongitudDelCampoEnBytes // 32 bits
char/int/float Arg1
char/int/float Arg2
....
char/int/float ArgN
[siguiente]

De acuerdo a la funcion que se haga se ignora el objeto y se pasa al
siguiente, todo lo que tengo que hacer es sumar la longitud del campo al
puntero y me queda apuntando al siguiente.
Todos mis intentos de escribirlo correctamente fracasaron, alguien me puede
decir como?.

Saludos.
Eduardo.
Toni
2005-01-06 00:33:32 UTC
Permalink
Post by Eduardo
Hola al grupo!
Soy una persona con conocimientos algo rudimentarios de C , me ha
surgido este problema y no encuentro la manera 'limpia y elegante' de
escribir la instruccion.
Tengo una serie de datos en memoria de longitud y tipo variables, y un
puntero al comienzo.
char TipoDeObjeto[7]
int LongitudDelCampoEnBytes // 32 bits
char/int/float Arg1
char/int/float Arg2
....
char/int/float ArgN
[siguiente]
De acuerdo a la funcion que se haga se ignora el objeto y se pasa al
siguiente, todo lo que tengo que hacer es sumar la longitud del campo
al puntero y me queda apuntando al siguiente.
Todos mis intentos de escribirlo correctamente fracasaron, alguien me
puede decir como?.
Saludos.
Eduardo.
No sé si entiendo lo que quieres hacer.

La aritmética de punteros funciona de forma que al incrementar el
puntero en 1 unidad se pasa al siguiente objeto. Por supuesto un puntero
sólo puede apuntar a un tipo de objeto.

Lo único que se me ocurre es usar punteros de tipo void *. Busca
información sobre eso.

Saludos

Toni
Eduardo
2005-01-06 03:05:42 UTC
Permalink
Es asi, el puntero es tipo void* , y no encuentro como incrementarlo
elegantemente con un valor de 32 bit que esta 7 bytes delante.
Salgo del paso con assembler inline:

void *buffer;
...............................
asm{
mov edx,buffer
mov edx,dword ptr [edx+7]
add buffer,edx
}

pero igual me gustaria saber como es la sintaxis correcta en C.

Saludos.
Eduardo.
Post by Toni
Post by Eduardo
Hola al grupo!
Soy una persona con conocimientos algo rudimentarios de C , me ha
surgido este problema y no encuentro la manera 'limpia y elegante' de
escribir la instruccion.
Tengo una serie de datos en memoria de longitud y tipo variables, y un
puntero al comienzo.
char TipoDeObjeto[7]
int LongitudDelCampoEnBytes // 32 bits
char/int/float Arg1
char/int/float Arg2
....
char/int/float ArgN
[siguiente]
De acuerdo a la funcion que se haga se ignora el objeto y se pasa al
siguiente, todo lo que tengo que hacer es sumar la longitud del campo
al puntero y me queda apuntando al siguiente.
Todos mis intentos de escribirlo correctamente fracasaron, alguien me
puede decir como?.
Saludos.
Eduardo.
No sé si entiendo lo que quieres hacer.
La aritmética de punteros funciona de forma que al incrementar el
puntero en 1 unidad se pasa al siguiente objeto. Por supuesto un puntero
sólo puede apuntar a un tipo de objeto.
Lo único que se me ocurre es usar punteros de tipo void *. Busca
información sobre eso.
Saludos
Toni
Carlos
2005-01-06 10:14:04 UTC
Permalink
Post by Eduardo
Es asi, el puntero es tipo void* , y no encuentro como incrementarlo
elegantemente con un valor de 32 bit que esta 7 bytes delante.
void *buffer;
...............................
asm{
mov edx,buffer
mov edx,dword ptr [edx+7]
add buffer,edx
}
pero igual me gustaria saber como es la sintaxis correcta en C.
La sintaxis en C sería así:

buffer += *(int *)(buffer + 7);

Pero hay que tener cuidado con el padding. Probablemente ese char[7] tenga 8
bytes y no 7.

Suerte.
Eduardo
2005-01-06 11:02:34 UTC
Permalink
Post by Carlos
buffer += *(int *)(buffer + 7);
Muchas gracias, habia hecho un monton de combinaciones y lo mas 'cercano a
la correcta fue buffer+=*(int*)(buffer[7]) , que por supuesto no anda
porque trata al valor de offset 7 como byte.
Post by Carlos
Pero hay que tener cuidado con el padding. Probablemente ese char[7] tenga 8
bytes y no 7.
El 7 es un valor de prueba, el formato real es:
[Objeto1: N bytes]
[Longitud: 4 bytes]
[Argumento1]
....
[ArgumentoK]
[Objeto2: N bytes]
[Longitud: 4 bytes]
..............
NULL // fin

Si bien para la mayoria de los casos N es 4 , puede tener cualquier valor.

Saludos.
Eduardo.
Lepton
2005-01-07 22:16:02 UTC
Permalink
On Thu, 6 Jan 2005, Carlos wrote:

# La sintaxis en C sería así:
#
# buffer += *(int *)(buffer + 7);

Hmmm.. no se, asi a ojo, si buffer es un puntero a void, no se puede
hacer aritmetica con el, asi que (buffer+7) dara error. Yo haria

buffer = (void*) ((int*)buffer + 7)

para avanzar buffer '7*sizeof(int)' bytes..

Lepton.
Eduardo
2005-01-08 11:39:15 UTC
Permalink
Post by Lepton
#
# buffer += *(int *)(buffer + 7);
Hmmm.. no se, asi a ojo, si buffer es un puntero a void, no se puede
hacer aritmetica con el, asi que (buffer+7) dara error.
Si, como void da error, le miento en la declaracion como 'extern char
*buffer' para que ande.
Post by Lepton
Yo haria
buffer = (void*) ((int*)buffer + 7)
para avanzar buffer '7*sizeof(int)' bytes..
Lepton.
Asi me incrementa el puntero en 28 bytes, lo que tengo que hacer es sumarle
el entero que apunta (buffer+7)

Saludos.
Eduardo.
Lepton
2005-01-09 00:31:50 UTC
Permalink
On Sat, 8 Jan 2005, Eduardo wrote:

# > Yo haria
# >
# > buffer = (void*) ((int*)buffer + 7)
# >
# > para avanzar buffer '7*sizeof(int)' bytes..
# >
# > Lepton.
#
# Asi me incrementa el puntero en 28 bytes, lo que tengo que hacer es sumarle
# el entero que apunta (buffer+7)

Perdona, no habia leido bien el mensaje original:

buffer = (void *) ((char *)buffer + *((char *)buffer + 7));

suponiendo que el 'entero' sea un byte. Seria muy raro que en buffer[7]
hubiera un 'int'..

Lepton.
Eduardo
2005-01-09 05:11:08 UTC
Permalink
Post by Lepton
buffer = (void *) ((char *)buffer + *((char *)buffer + 7));
suponiendo que el 'entero' sea un byte. Seria muy raro que en buffer[7]
hubiera un 'int'..
La estructura es:
[CodigoDeObjeto1(N bytes)][LongitudTotal(M1 bytes)][Argumentos(M1-N bytes)]
[CodigoDeObjeto2(N bytes)][LongitudTotal(M2 bytes)][Argumentos(M2-N bytes)]
...................

N en general es 4 y Mx son 4 bytes , inicie el hilo porque no podia escribir
correctamente la adicion al puntero para pasar de un elemento al siguiente
en un caso general (por ejemplo N=7).

Saludos.
Eduardo.
Lepton
2005-01-10 17:03:52 UTC
Permalink
On Sun, 9 Jan 2005, Eduardo wrote:

# "Lepton" <***@jazzfree.com> wrote in message
# news:***@ID-130846.user.uni-berlin.de...
# >
# > Perdona, no habia leido bien el mensaje original:
# >
# > buffer = (void *) ((char *)buffer + *((char *)buffer + 7));
# >
# > suponiendo que el 'entero' sea un byte. Seria muy raro que en buffer[7]
# > hubiera un 'int'..
# >
#
# La estructura es:
# [CodigoDeObjeto1(N bytes)][LongitudTotal(M1 bytes)][Argumentos(M1-N bytes)]
# [CodigoDeObjeto2(N bytes)][LongitudTotal(M2 bytes)][Argumentos(M2-N bytes)]
# ...................
#
# N en general es 4 y Mx son 4 bytes , inicie el hilo porque no podia escribir
# correctamente la adicion al puntero para pasar de un elemento al siguiente
# en un caso general (por ejemplo N=7).

Podrias hacer algo asi (suponiendo que la LongitudTotal incluye el
codigo, la longitud total y los argumentos, o sea que la longitud de
los argumentos es Longitud - sizeof(Codigo) - sizeof(Longitud))

void recorrer(void *buffer) {
struct elemento {
int codigo;
int longitud;
char args[0];
} *ptr;

for(ptr = (struct elemento *)buffer;
ptr->codigo != 0;
ptr = (struct elemento *)((char *)ptr + ptr->longitud)) {

/* printf("ptr = %p\n", ptr); */
printf("codigo = %d\n", ptr->codigo);
printf("longitud = %d\n", ptr->longitud);
printf("argumentos = \"%.*s\"\n",
ptr->longitud - sizeof(ptr->codigo) - sizeof(ptr->longitud),
ptr->args);
}
}

como prueba:

int main(void) {
char *buf = "\1\0\0\0\xC\0\0\0abcd\2\0\0\0\xB\0\0\0xyz\0\0\0\0";

recorrer(buf);
}

Lepton.
Eduardo
2005-01-10 18:20:45 UTC
Permalink
Post by Lepton
Podrias hacer algo asi (suponiendo que la LongitudTotal incluye el
codigo, la longitud total y los argumentos, o sea que la longitud de
los argumentos es Longitud - sizeof(Codigo) - sizeof(Longitud))
void recorrer(void *buffer) {
struct elemento {
int codigo;
int longitud;
char args[0];
} *ptr;
for(ptr = (struct elemento *)buffer;
ptr->codigo != 0;
ptr = (struct elemento *)((char *)ptr + ptr->longitud)) {
/* printf("ptr = %p\n", ptr); */
printf("codigo = %d\n", ptr->codigo);
printf("longitud = %d\n", ptr->longitud);
printf("argumentos = \"%.*s\"\n",
ptr->longitud - sizeof(ptr->codigo) - sizeof(ptr->longitud),
ptr->args);
}
}
int main(void) {
char *buf = "\1\0\0\0\xC\0\0\0abcd\2\0\0\0\xB\0\0\0xyz\0\0\0\0";
recorrer(buf);
}
Lepton.
Funciona perfectamente (el compilador de Borland no me acepta 'char
args[0]' en la definicion de la estrucura) y es mas apropiado usar una
estructura que un puntero generico, porque al fin y al cabo los dos primeros
elementos (descriptor+longitud) son fijos. Tiene como restriccion el padding
,la longitud debe estar a un offset multiplo de 4 (al menos asi me lo
compila Borland en 32 bits).
En mi caracter de aprendiz de C, el problema ya no era como incrementar el
puntero en este caso particular y asi seguir con el resto (de hecho ya lo
habia resuelto 'ilegalmente'), sino como coño se deberia escribir en 'C
puro' para un caso general.

Saludos.
Eduardo.
Lepton
2005-01-10 20:33:13 UTC
Permalink
On Mon, 10 Jan 2005, Eduardo wrote:

# "Lepton" <***@jazzfree.com> escribió en el mensaje
# news:***@ID-130846.user.uni-berlin.de...
# >
# > Podrias hacer algo asi (suponiendo que la LongitudTotal incluye el
# > codigo, la longitud total y los argumentos, o sea que la longitud de
# > los argumentos es Longitud - sizeof(Codigo) - sizeof(Longitud))
# >
# > void recorrer(void *buffer) {
# > struct elemento {
# > int codigo;
# > int longitud;
# > char args[0];
# > } *ptr;
# >
# > for(ptr = (struct elemento *)buffer;
# > ptr->codigo != 0;
# > ptr = (struct elemento *)((char *)ptr + ptr->longitud)) {
# >
# > /* printf("ptr = %p\n", ptr); */
# > printf("codigo = %d\n", ptr->codigo);
# > printf("longitud = %d\n", ptr->longitud);
# > printf("argumentos = \"%.*s\"\n",
# > ptr->longitud - sizeof(ptr->codigo) - sizeof(ptr->longitud),
# > ptr->args);
# > }
# > }
# >
# > como prueba:
# >
# > int main(void) {
# > char *buf = "\1\0\0\0\xC\0\0\0abcd\2\0\0\0\xB\0\0\0xyz\0\0\0\0";
# >
# > recorrer(buf);
# > }
# >
# > Lepton.
#
# Funciona perfectamente (el compilador de Borland no me acepta 'char
# args[0]' en la definicion de la estrucura) y es mas apropiado usar una

Puedes usar args[1], lo importante es que haya algo que se pueda
direccionar..

# estructura que un puntero generico, porque al fin y al cabo los dos primeros
# elementos (descriptor+longitud) son fijos. Tiene como restriccion el padding
# ,la longitud debe estar a un offset multiplo de 4 (al menos asi me lo
# compila Borland en 32 bits).

Por eso decia en un post anterior que tener un 'int' en buffer[7] era
raro. En principio no deberia ser problema (a menos que uses un
procesador que obligue que los datos esten alineados), pero supongo
que es recomendable usar algun tipo de padding.

# En mi caracter de aprendiz de C, el problema ya no era como incrementar el
# puntero en este caso particular y asi seguir con el resto (de hecho ya lo
# habia resuelto 'ilegalmente'), sino como coño se deberia escribir en 'C
# puro' para un caso general.

No se si mi solucion es la mejor, pero yo lo haria asi, dando por
supuesto que no puedes cambiar la forma de definir el buffer (yo
usaria una lista enlazada)

Lepton.

Eduardo
2005-01-10 17:04:12 UTC
Permalink
Muchas gracias a todos los que me contestaron, juntando sus comentarios y
ensayando un poco llegue a la expresion 'C legal' que buscaba, sin necesidad
de 'mentir' con el tipo de puntero.

#define OFFSET_LEN 7
void *test(void *buffer){
.............................
.............................
(char*)buffer += *(int*)((char*)buffer+OFFSET_LEN);
return buffer;
}

Saludos.
Eduardo.
Loading...