Se que se debería declarar char c[50]
por ejemplo pero quería ver que pasaba.
No sé que tan mal este el programa ni cuál sea el error
No sientes que ambas oraciones se contradicen?
Porque hace eso?
Simulemos tu programa, y vamos a ver el stack y lo que pasa instruccion
a instruccion. En mi caso siempre me decia que el largo era 2, asi que eso es
lo que vamos a reproducir aqui:
De tus variables:
int i;
char c;
char* ptr;
Tendremos un stack que se vera algo como1:
Direccion | Valores
0x1 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | // char* ptr;
0x9 | 0x0 | // char c;
0xA | 0x0 | 0x0 | 0x0 | 0x0 | // int i;
Luego va esta linea:
ptr=&c;
Asi que le damos a ptr
la direccion de c
.
Direccion | Valores
0x1 | 0x9 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | // char* ptr;
0x9 | 0x0 | // char c;
0x10 | 0x0 | 0x0 | 0x0 | 0x0 | // int i;
Y luego lees:
scanf("%s",ptr);
Supongamos que el usuario ingresa 'Hola'. Como crees que se vera el stack?
Intenta hacerlo tu antes de continuar.
Lee primero la H
:
Direccion | Valores
0x1 | 0x9 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | // char* ptr;
0x9 | 0x48 (H) | // char c;
0x10 | 0x0 | 0x0 | 0x0 | 0x0 | // int i;
Y si te das cuenta ya te terminaste la memoria que asignaste para la palabra,
pero scanf
no sabe eso, asi que no se detendra, seguira escribiendo en las
siguientes direcciones de memoria. Tu stack puede parar algo similar a esto:
Direccion | Valores
0x1 | 0x9 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | // char* ptr;
0x9 | 0x48 (H) | // char c;
0xA | 0x6f (o) | 0x6c (l) | 0x61 (a) | 0x0 (\0) | // int i;
Ya aqui ya estamos muy mal, has sobreescrito i
.
Ahora vamos a tu for
, primero que nada, a i
le damos el valor de 0
.
Direccion | Valores
0x1 | 0x9 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | // char* ptr;
0x9 | 0x48 (H) | // char c;
0xA | 0x0 | 0x0 | 0x0 | 0x0 | // int i;
Lees en (ptr+i)
(en la direccion 0x9
), que seria la H
, y como no es igual
a \0
incrementamos i
en 1.
Direccion | Valores
0x1 | 0x9 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | // char* ptr;
0x9 | 0x48 (H) | // char c;
0xA | 0x1 | 0x0 | 0x0 | 0x0 | // int i;
Ahora cuando lees en (ptr+i)
(en la direccion 0xA
), y como no es igual
a \0
incrementamos i
en 1. Ahora el stack es:
Direccion | Valores
0x1 | 0x9 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | 0x0 | // char* ptr;
0x9 | 0x48 (H) | // char c;
0xA | 0x2 | 0x0 | 0x0 | 0x0 | // int i;
Finalmente lee en 0xB
, y como esa direccion tiene el valor de 0x0
(el \0
), ya termina el loop, dandole a i
el valor final de 2
.
Comportamiendo indefinido
El leer o escribir en memoria que tu no has asignado es comportamiendo
indefinido, eso significa que no se puede asegurar que es lo que sucedera en
cada caso.
El error en este caso es tratar de escribir multiples caracteres en un buffer
que solo puede recibir uno, tienes un buffer overflow.
1: Dejare cada variable en una linea por claridad. Nota que lo mas probable
no es que esten inicializadas a 0, sino que tengan valores basura.