En principio también se podría hacer un programa para operar aritméticamente con caracteres char;
Eso no anda bien, porque hay límites desde el mismo lenguaje.
Para indicar un vector de elementos de tipo char, hay que reservar memoria cada vez,
intentando agrandar el tamaño del vector, así:
char *number; /* Declaración de puntero a dirección de memoria RAM conteniendo char */
number = malloc(2); /* Reserva 2 bytes: 1 byte para un dígito y 1 byte para marca de final de string */
number[1] = '\0'; /* Marca de fin de string (código ASCII 0) */
number[0] = '0'; /* El único dígito disponible lo pongo a '0' (código ASCII 48) */
/* Aquí number está representando el número natural intuitivo 0 */
.....
/* Ahora intento que number represente un número con 230 dígitos. */
/* Antes de lograrlo, necesito reservar 230 bytes para los dígitos, y 1 más para el final de string. */
/* Se usa la función realloc() para reservar memoria suficiente, y sin borrar el contenido previo: */
number = realloc(number, 231);
number[230] = '\0';
Ahora bien, fíjate que en la sentencia que usa
realloc(), el segundo parámetro tiene que ser un número entero, pero no cualquier número, sino uno de tipo
size_t.
El tipo de datos size_t tiene un valor máximo posible.
Más aún, su valor máximo está acotado por el máximo valor admitido por el tipo de datos
uintmax_t.
En los sistemas actuales, este valor anda más o menos por \( 2^{64}-1 \).
O sea que la cantidad de dígitos de un array de char podría ser a lo sumo \( 2^{64}-1 \).
No hay (o no se me ocurre) manera en que pueda agregarle dígitos de uno en uno, con
realloc().
Tendría que poder agregarle bytes "detrás", y aunque se me ocurren algunos modos extravantes de hacerlo con la familia de funciones
xx_alloc(), es muy probable que sean malas prácticas de programación (o sea, dando resultados no previsibles).
En resumidas cuentas, el lenguaje presenta limitaciones al tamaño de un vector de datos de un tipo dado.
----------------
En cambio, al usar una lista enlazada, se ha de reservar memoria cada vez para un único dígito (y el enlace link), lo cual es más engorroso, pero desde un punto de vista teórico es correcto, porque el lenguaje no presenta limitación alguna en cuanto a la cantidad de veces que esto puede hacerse.
Así que el número de dígitos así expuesto es ilimitado.
La sintaxis y especificaciones del lenguaje no imponen limitaciones, y por lo tanto me permite representar cualquier número natural, por grande que sea.
Esta posibilidad es abstracta, o sea que no difiere del todo del carácter mental que tienen los naturales intuitivos.
Siguen siendo un modelo de los números naturales, incluso a nivel abstracto, mental.
Si tenemos una buena máquina, es posible representar el número natural que queramos, por grande que sea.
En cualquiera de los casos, la memoria se va a gastar antes o después, tanto metiendo los datos directamente en las direcciones de memoria o por medio de comandos de más alto nivel (matrices o lo que sea).
Entonces, la cuestión es si eso sería un modelo de los números naturales o un modelo de cómo nosotros usamos los números naturales:
Claro que se va a gastar.
Pero eso no es una imposición de la sintaxis del lenguaje.
Si estás obligado a usar
size_t, entonces el lenguaje mismo te acota la cantidad de dígitos a un número finito.
En cambio, mediante la técnica de lista enlazada, el lenguaje no impone ninguna restricción,
y en cambio las limitaciones de memoria dependen de "la máquina" o "sistema" en que el programa se compila y corre.
El estándar que define el lenguaje C es muy general respecto el tipo de "máquina" en que el lenguaje C va a correr. No especifica demasiados detalles, dejando la puerta abierta a una gran variedad de posibilidades.
Esto se llama:
la máquina abstracta de C.
O sea que, en realidad, al escribir un programa, estamos escribiéndolo para que corra en esa "máquina abstracta", y no en una máquina real.
Luego, cada compilador hace sus elecciones acorde a la máquina real en que se va a ejecutar el programa.
Pero, como bien ha dicho Carlos, un programa es algo mental, abstracto.
Yo podría "correr" el programa en mi cabeza, haciendo una simulación con la imaginación.
Ahí no tendría problemas de memoria RAM (eso creo, no lo sé).
O bien, podría considerar que todos los seres vivos del Universo juntamos "RAM" para representar dígitos, y así vamos representando números cada vez más grande.
La posibilidad de representar un número en la realidad depende de la imaginación...
y también de la cantidad de materia del Universo, útil para representar información.
Pero esto no interesa demasiado, porque, como vos decís:
Yo, lo que sí veo, es que supone “enseñarle” al ordenador a operar de forma más parecida a un humano;
Eso mismo. Lo que hacemos es definir una estructura que, en abstracto, "permite" representar cualquier número natural, y luego sobre esa estructura definimos las operaciones y relaciones típicas de los naturales.
"Eso" da un sistema que funciona/opera/trabaja igual que los naturales, y podemos "extraer conclusiones sobre ellos".
Las conclusiones, como insiste Ivorra por ahí, son intuitivas.
El programa no podrá extraer todas las conclusiones sobre sus números.
No obstante, las conclusiones que obtendremos sobre estas entidades serán las mismas que las que obtendremos sobre los números naturales. Son sistemas isomorfos.
Sin embargo, cuando un programa de alto nivel se compila para que opere en su código, quizá no hace otra cosa que operar con una lógica humana, porque por muy código máquina que sea, ese código lo hemos inventado los humanos, no las máquinas.
Pienso que está mal razonar así.
Tu idea de usar "strings" para representar dígitos es una "idea humana", pero te he mostrado que no sirve, porque el lenguaje tiene limitaciones en su definición, o sea, hay razones técnicas que hacen que C, inventado por humanos, no sea capaz de representar números arbitrarios mediante meras strings.
En cuanto a los lenguajes de alto nivel, no puedo decir nada, porque no sé cómo están definidos (porque no lo he estudiado), ni cómo están implementados.
Por ejemplo, en Python se supone que hay un tipo de datos "integer" que representaría cualquier número natural. ¿Es cierto esto?
Si se usa la técnica de un array, ya sea de caracteres o de enteros-de-máquina, lo que fuere, y si el código no está escrito con el suficiente cuidado, puede que haya un máximo de dígitos, y entonces no serían "enteros cualesquiera" los que Python permite.
En realidad esto no lo sé. Hace un tiempo estuve buscando información sobre esto, y no encontré nada concreto. Me pareció que Python, en la práctica, tiene (o tenía) limitaciones en el número de dígitos (quizás esto de los \( 2^{64} \) dígitos aplique a Python), pero es posible que me equivoque.
Después de todo, he mostrado que es posible definir una estructura de datos (recursiva) que permite representar cualquier entero.
Así que Python puede estar bien, aunque para saberlo debiera analizar el código conque está escrito.
(No me hagan discutir diciendo cosas como que "¿qué pasa si estamos en un Universo en que vemos/intuimos los naturales creyendo que son los de verdad, pero un demonio desde afuera del Universo considera que los naturales que vemos son no-estándar?").
Pero es que ahí es donde yo creo que está el quid de la cuestión, tarde o temprano vamos a llegar a discutir sobre eso: ¿Es objetivo el concepto de “numerable” o depende del “observador” que va llevando la cuenta? ¿Cuáles son los naturales estándar o no estándar, de qué o de quién depende eso? ¿Puede existir un “demonio” que use una base numérica cuya “cantidad” de símbolos, desde nuestro punto de vista, sea infinita? Si la respuesta la consideramos afirmativa ¿deberíamos considerarlo relevante o hacemos caso omiso del demonio ese? Si hacemos caso del demonio o del marciano o lo que sea, por lo menos podríamos suponer o dar por bueno que tanto él como nosotros usamos alguna base numérica y, con ella, un método para hacer sumas y multiplicaciones.
Y a partir de aquí, antes de otras cosas, lo que tenemos que hacer es ponernos de acuerdo sobre si siempre que alguien usa una base simbólica, y unas reglas concretadas por alguien, está usando números que podemos llamar naturales.
Si bien todo eso es posible, especular sobre seres extraños y demonios va más allá de lo que podemos comprobar empíricamente.
Es una especulación sin demasiado sentido, porque no hay hechos en los que apoyarse para discutir.
Por eso no creo que me vaya a ir por ahí.