3

Creo un arreglo con limite de 5, se supone que solo podría ingresar 4 caracteres, pero me permite ingresar una cantidad infinita de ellos, por que pasa esto?

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {

    char nombre[5];

    printf("Dame tu nombre: ");

    scanf("%s",nombre);

    printf("tu nombre es: %s",nombre);


    return 0;

}
HeytalePazguato
  • 4,849
  • 2
  • 7
  • 26
  • ¿Responde esto a tu pregunta? [¿Cómo evitar un desbordamiento de búfer cuando se pide una cadena con scanf?](https://es.stackoverflow.com/questions/383852/c%c3%b3mo-evitar-un-desbordamiento-de-b%c3%bafer-cuando-se-pide-una-cadena-con-scanf) – MrDave1999 Jan 20 '22 at 01:04

2 Answers2

4

se supone que solo podría ingresar 4 caracteres

Técnicamente no es así.

Si creas un array de 5 elementos, podrás almacenar en dicho array un máximo de 5 elementos.

Recordemos que un array no es más que un bloque de memoria. En este caso el bloque tiene 5 bytes:

 00 01 02 03 04 05 06 ...
| -- nombre -- | -- otras varaibles --

pero me permite ingresar una cantidad infinita de ellos, por que pasa esto?

Esto pasa por dos razones:

  1. Nadie va a comprobar si se superan los límites de un array. El único que en este caso podría hacer algo al respecto es el Sistema Operativo y solo va a actuar cuando escribas fuera de la memoria asociada a tu proceso. En ese caso actuará matando tu aplicación para que no corrompas memoria de otros procesos

  2. scanf no conoce (tampoco es que le importe mucho) el tamaño de tu array. Tu le estás diciendo que quieres leer una cadena de caracteres, luego la función hará exactamente eso: Leer caracteres hasta que se encuentre un separador (espacio, tabulador, salto de línea). Que luego haya o no espacio para almacenar esa cadena ya es cosa tuya. Es por eso que scanf se considera una función insegura y se recomienda, por tanto, el uso de scanf_s

Lo que acaba sucediendo en tu programa es que scanf, al leer una cadena de más de 4 caracteres, empieza a escribir en posiciones de memoria que pertenecen a tu programa pero no a tu array, es decir, posiciones de memoria donde podrían encontrarse otras variables. Esto generalmente acaba provocando que tu aplicación se comporte de forma errática.

La mejor solución sería usar scanf_s. Esta es, digamos, la versión segura de scanf. Su uso no es muy diferente del que tiene actualmente scanf:

scanf_s("%s", nombre, sizeof(nombre));

Este mecanismo impide que se escriba fuera de los límites de tu array.

Otra solución sería, como te comentan en la otra respuesta, limitar la longitud de la cadena a leer. Lo que sucede en este caso es que tienes que acordarte de restar uno a la longitud del array:

scanf("%4s", nombre); 
eferion
  • 49,291
  • 5
  • 30
  • 72
-2

Buen día,

Puedes limitar el número de caracteres aceptado por scanf si defines el número de caracteres utilizando %5s (El número 5 define el número de caracteres aceptado)

Si agregas eso a tu código el número de caracteres ingresados se limita a 5

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {

    char nombre[5];

    printf("Dame tu nombre: ");

    scanf("%5s",nombre);

    printf("tu nombre es: %s",nombre);


    return 0;

}
HeytalePazguato
  • 4,849
  • 2
  • 7
  • 26
  • Si el array es de longitud 5, solo podrás leer 4 caracteres. Si configuras `scanf` para que lea 5, se almacenarán 6 caracteres ... el último no va a entrar en el array y pisará memoria de otras variables – eferion Jan 19 '22 at 08:16
  • Así es, lo único que mostré en el código es el ejemplo de como limitar el scanf – HeytalePazguato Jan 19 '22 at 08:18
  • 1
    Ya que lo limitas, límitalo bien. tu código es erróneo – eferion Jan 19 '22 at 08:18
  • Es un ejemplo... – HeytalePazguato Jan 19 '22 at 08:19
  • Si el ejemplo es erróneo entonces quien utilice tu ejemplo como plantilla para sus propios propósitos heredará los errores y no le funcionará. Si pones un ejemplo, debe ser válido y correcto – eferion Jan 19 '22 at 10:42
  • Debes dejar espacio para el *caracter nulo*, es por eso que debe ser `scanf("%4s", nombre);` – MrDave1999 Jan 20 '22 at 01:02