Incremento de punteros

Iniciado por NathanD, 29 Marzo 2013, 17:43 PM

0 Miembros y 1 Visitante están viendo este tema.

NathanD

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:


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.

x64core

Estas seguro que esa es la salida de ese codigo?
Recordar que haces un pos incremento.

NathanD

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.

naderST

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

x64core

#4
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):



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

naderST

#5
Compilado con MinGW:



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);

rir3760

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
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

x64core

Ya veo, yo realmente no uso esos compialdores y creo que jamas cambiaria a esos apestosos compiladores
Tampoco me saldria del estandar :P

85

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
Me cerraron el Windows Live Spaces, entonces me creé un WordPress XD
http://etkboyscout.wordpress.com/

mr.blood

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