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:
#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;
}
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.
Estas seguro que esa es la salida de ese codigo?
Recordar que haces un pos incremento.
Cita de: x64Core en 29 Marzo 2013, 18:09 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.
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
Cita de: NathanD en 29 Marzo 2013, 18:15 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
#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.
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);
Cita de: NathanD en 29 Marzo 2013, 17:43 PMBuenas, 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>.
Cita de: x64Core en 29 Marzo 2013, 18:38 PMYo 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:
Introduce una frase: hola, mundo
0x00144610 = h
0x00144611 = o
0x00144612
0x00144611
Con gcc 4.5.3 (CygMing):
Introduce una frase: hola, mundo
0x20010228 = h
0x20010229 = o
0x2001022a
0x20010229
Con Visual C++ 2008 Express:
Introduce una frase: hola, mundo
00373E30 = h
00373E31 = o
00373E31
00373E31
Un saludo
Ya veo, yo realmente no uso esos compialdores y creo que jamas cambiaria a esos apestosos compiladores
Tampoco me saldria del estandar :P
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
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
Cita de: 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
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
Él ingresa en este orden:
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.