Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: NathanD en 29 Marzo 2013, 17:43 pm



Título: Incremento de punteros
Publicado por: NathanD en 29 Marzo 2013, 17:43 pm
Buenas, mi problema esta vez es el siguiente.

En realidad me gustaría que me explicarais el porqué de este resultado de este código.

El código:
Código
  1. #include <stdio.h>
  2.  
  3. #define MAXLINE 60
  4.  
  5. int main()
  6. {
  7. char *ptr;
  8. ptr = (char*) malloc(MAXLINE * sizeof(char) );
  9.  
  10. printf("Introduce una frase: ");
  11. fgets(ptr, MAXLINE+1, stdin);
  12.  
  13. printf("\n%p = %c", ptr,*ptr);
  14. ptr++;
  15. printf("\n%p = %c", ptr, *ptr);
  16.  
  17. printf("\n\n%p %p", ptr, ptr++);
  18.  
  19.  
  20. return 0;
  21. }

El resultado:
(http://i.imgur.com/5JV0qtX.jpg)

Mi duda es, ¿por qué hace el incremento "al revés"? Después de haber incrementado el puntero en uno para que apunte al segundo carácter (ahí en cambio no hay problema), luego en el printf no es la misma dirección de memoria.

Saludos y gracias de antemano.


Título: Re: Incremento de punteros
Publicado por: x64core en 29 Marzo 2013, 18:09 pm
Estas seguro que esa es la salida de ese codigo?
Recordar que haces un pos incremento.


Título: Re: Incremento de punteros
Publicado por: NathanD en 29 Marzo 2013, 18:15 pm
Estas seguro que esa es la salida de ese codigo?
Recordar que haces un pos incremento.
Sí, lo he probado con más de un compilador.


Título: Re: Incremento de punteros
Publicado por: naderST en 29 Marzo 2013, 18:26 pm
Lo que ocurre es que los argumentos se están evaluando de derecha a izquierda, esto ocurre dependiendo del compilador, la arquitectura, el tipo de argumento, y la convención de llamada de la función que estás llamando.

Esto es un comportamiento que no está especificado en el estándar y depende de la plataforma.

Fuente: http://stackoverflow.com/questions/621542/compilers-and-argument-order-of-evaluation-in-c


Título: Re: Incremento de punteros
Publicado por: x64core en 29 Marzo 2013, 18:38 pm
Sí, lo he probado con más de un compilador.

Yo no estoy seguro lo que dice naderST, pero aun si fuera cierto no tiene sentido

Código:
#include <stdio.h>
 
#define MAXLINE 60
 
int main()
{
char *ptr;
ptr = (char*) malloc(MAXLINE * sizeof(char) );
 
printf("Introduce una frase: ");
fgets(ptr, MAXLINE+1, stdin);
 
printf("\n%p = %c", ptr,*ptr);
ptr++;
printf("\n%p = %c", ptr, *ptr);
 
printf("\n\n%p %p", ptr, ptr++);
 
getchar();
 
return 0;
}

Si aun los argumentos se evaluaran de derecha a izquierda en la linea del tercer printf ptr deberia contener la dirección 00512421,
además he notado que en el tercer printf el valor de ptr vale 00512422, valor inicial 00512420 y solamente se hace un incremento.
¿Que compilador utilizas?


Agregado:

He compilado con VC++ y Dev-Cpp(MinGW32):

(http://s3.postimg.org/xhg9c824j/Untitled.png)

Facil como pasarle una mirada al codigo.
He corregido, el segundo argumento pasado a la tercera llamada a printf deberia contener 00512421.


Título: Re: Incremento de punteros
Publicado por: naderST en 29 Marzo 2013, 18:54 pm
Compilado con MinGW:

(http://imagenhost.com.ve/viewimage/53/)

EDIT:
Citar
Yo no estoy seguro lo que dice naderST, pero aun si fuera cierto no tiene sentido

No me creas a mí, revisa el enlace que coloqué de stack overflow y si no me equivoco es algo que está contemplado en el estándar pero no está especificado.

Si te fijas bien, en el tercer printf (cuarto en realidad) antes de ser llamado ptr vale 00512421, al evaluarse de derecha a izquierda se hace un pos-incremento quedando la llamada de la siguiente manera:

printf("\n\n%p %p", 00512422, 00512421);


Título: Re: Incremento de punteros
Publicado por: rir3760 en 29 Marzo 2013, 19:14 pm
Buenas, mi problema esta vez es el siguiente.

En realidad me gustaría que me explicarais el porqué de este resultado de este código.
El primer cambio a realizar es: antes de utilizar la función malloc debes tener acceso a su prototipo, eso lo consigues incluyendo el encabezado <stdlib.h>.

Yo no estoy seguro lo que dice naderST
naderST esta en lo correcto: el orden en que se evalúan los operandos de una expresión y cuando exactamente aplican los efectos laterales no lo define el lenguaje.

Si modificamos el programa ligeramente (inclusión de <stdlib.h> y unos cuantos avances de linea) algunas salidas mas son:

Con Lcc-win32:
Código:
Introduce una frase: hola, mundo
0x00144610 = h
0x00144611 = o
0x00144612
0x00144611

Con gcc 4.5.3 (CygMing):
Código:
Introduce una frase: hola, mundo
0x20010228 = h
0x20010229 = o
0x2001022a
0x20010229

Con Visual C++ 2008 Express:
Código:
Introduce una frase: hola, mundo
00373E30 = h
00373E31 = o
00373E31
00373E31

Un saludo


Título: Re: Incremento de punteros
Publicado por: x64core en 29 Marzo 2013, 19:24 pm
Ya veo, yo realmente no uso esos compialdores y creo que jamas cambiaria a esos apestosos compiladores
Tampoco me saldria del estandar :P


Título: Re: Incremento de punteros
Publicado por: 85 en 30 Marzo 2013, 12:48 pm
http://en.wikipedia.org/wiki/X86_calling_conventions

Citar
cdecl
The cdecl (which stands for C declaration) is a calling convention that originates from the C programming language and is used by many C compilers for the x86 architecture.[1] In cdecl, subroutine arguments are passed on the stack. Integer values and memory addresses are returned in the EAX register, floating point values—in the ST0 x87 register. Registers EAX, ECX, and EDX are caller-saved, and the rest are callee-saved.
In context of the C programming language, function arguments are pushed on the stack in the reverse order.

y por supuesto printf es cdecl

http://msdn.microsoft.com/es-AR/library/984x0h58(v=vs.80).aspx
http://www.agner.org/optimize/calling_conventions.pdf

y más información para otra arquitectura
http://msdn.microsoft.com/en-us/library/ms235286(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/7kcdt6fy(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/9b372w95(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/zthk2dkh(v=vs.80).aspx


Título: Re: Incremento de punteros
Publicado por: mr.blood en 30 Marzo 2013, 19:57 pm
Aqui teneis otro ejemplo de eso: http://www.portalhacker.net/index.php/topic,126837.0.html

El printf toma los argumentos de derecha a izquierda, por eso muestra "Hola" en vez de "aloH" ;).

Sa1uDoS


Título: Re: Incremento de punteros
Publicado por: naderST en 31 Marzo 2013, 17:52 pm
Aqui teneis otro ejemplo de eso: http://www.portalhacker.net/index.php/topic,126837.0.html

El printf toma los argumentos de derecha a izquierda, por eso muestra "Hola" en vez de "aloH" ;).

Sa1uDoS

Ese código tiene un detalle y es que dependiendo del compilador la salida va  a variar, prueba compilarlo con VC++ y te imprimirá aloH


Título: Re: Incremento de punteros
Publicado por: 85 en 31 Marzo 2013, 18:42 pm
Él ingresa en este orden:

Código:
push('H');//1
push('o');//2
push('l');//3
push('a');//4

por lo que en una pila uno espera que estos elementos salgan así:

Citar
-> 4, 3, 2, 1


Entonces al llamar a printf que recibe los parámetros a la inversa (derecha a izquierda), entonces quedaría así:

Citar
                                   //1(h)   2(o)   3(l)    4(a)
printf("%c%c%c%c\n",pop(),pop(),pop(),pop());//right to left (1,2,3,4 <-)

El primer parámetro recibido sería el marcado cómo 4, luego el 3 y así.

En visual C++ 6 y 2010 imprime "Hola".
más datos, WINXP SP3 32BITS XD.
Sería raro un compilador que no respetara esto ya que es parte de la convención de llamada de C.