micro reto de la semana

Empezamos con uno muy fácil, apto para todos los públicos ¿Qué imprime esta sentencia? ¿y por qué?

En C:

printf("hola" + 2);

C++:

cout << "hola" + 2;

Java:

System.out.print("hola" + 2);

Python, Perl, Ruby (mismo programa, distintos resultados)

print "hola" + 2

c-shell:

echo "hola" + 2

C#:

Console.WriteLine("hola" + 2);

LUA:

print ("hola" + 2)

Lo de "qué imprime" se puede considerar una pregunta retórica ya que con escribir el programa correspondiente ya tienes la solución. La interesante es sale lo que esperabas y sobre todo el porqué...

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Vaya, se acaba la semana y ningún lanzao

Y eso que era un reto sencillo. Lo que más se parece a una respuesta de 1 octavo del reto es el mensaje de Marton.Kuzner, pero ni siquiera llega a responder explícitamente.

Viene a decir (y no explícitamente) que la expresión "hola" es equivalente a X, donde X es la dirección de memoria donde se guarda el primer elemento de la cadena. Pero eso no es verdad, porque entonces sizeof("hola") sería el tamaño de una dirección de memoria (4 en arquitecturas de 32 bits) y todos sabemos que no es eso.

Retiro mi pedido de disculpas

Acabo de percatar que la persona que critica mi respuesta ni siquiera tiene idea de que es un arreglo de caracteres y de su tan conocida relación y equidad con los punteros.

¿He de suponer que sujetos como éste son los que realizan la traduccion de "Thinking in C++"?, si es asi, he perdido total interes en el proyecto.

lamento comunicar que si uno declarara un string X para almacenar el "hola", X sería internamente UN PUNTERO. Uno puede encontrarlo en cualquier referencia... los strings son arreglos de caracteres... y los arreglos son punteros. Todos los arreglos son internamente punteros (con unas pequeñas limitaciones, pero punteros al fin), únicamente que ademas de ser punteros, el compilador gestiona un espacio en el stack del tamaño que uno le de al arreglo. Si uno en vez de declarar un arreglo, declara un puntero, uno deberá gestionar a mano memoria dinamica para tener donde guardar los caracteres. Y es mas, una vez que lo hacemos, al puntero lo podemos usar igual que a un string y/o aun array, exactamente igual.

por citar:

char a[5]; //declaramos un arreglo de char
char *b; //declaramos un puntero a char

a = "hola"; //asignamos un valor
b = a; //asignamos a b la misma direccion que internamente tiene a

printf(b); //es equivalente a printf(a)

b = "chau"; //es equivalente a a = "chau";

b[3] = 'o'; //es equivalente a a[3] 'o';

b = &a[0]; //es equivalente a b = a; dado que le asigna la direccion del primer elemento de a

b = a + 1; //es equivalente a b = &a[1]; haciendo que b apunte a la segunda letra

Para profundizar:
http://www.gamedev.net/reference/articles/article1697.asp

PD: ¿por que mi respuesta valdría un octavo, si la cantidad de lenguajes propuesta en el reto son 7 ??

Imagen de darkgnu

A menos que tu apellido real

A menos que tu apellido real sea Richie, Thompson, Stroustrup, Pike o Meyer acabas de meter la pata hasta el cuezo

----------------------------------------------------------
$ mv *.net /dev/null

Imagen de david.villa

La lista de traductores y

La lista de traductores y colaboradores que participan en la traducción de PensarEnC++ está en su página web si te interesa. Lamentablemente no contamos con paco para esta tarea, ya nos gustaría. Si te sigue interesando el proyecto de traducción eres bienvenido, yo me encargo de la coordinación. Más info en la página que he enlazado.

En reto en realidad son 8 partes, no 7:

  1. C/C++ Como ambas usan cadenas de caracteres, es la misma situación.
  2. Java:
  3. Python
  4. Perl
  5. Ruby
  6. c-shell:
  7. C#:
  8. LUA:

Aunque se llame “reto”, esto no es un duelo a muerte al amanecer, no hay premio ni castigo. Creo que no deberías tomártelo tan a pecho. Sólo es una excusa para hablar de detalles curiosos de los lenguajes de programación que a veces nos traen de cabeza. No acabo de comprender tu actitud beligerante (al menos eso me parece, puede que me equivoque). Nadie te ha provocado (o al menos eso me parece).

No soy portavoz de ningún colectivo, grupo o facción. Mi opinión es personal e intransferible.

Nain, C y C++ no son equivalentes

La expresión está desprovista de contexto, por tanto en C++ no está definida. Podría imprimir cualquier cosa. Depende de si existe o no una redefinición del operador de suma de cadenas y enteros.

Ya salió el listo...

Obviamente no tienes ni remota idea de lo que hablas. Baja los humos y estudia.

char a[]="hola";
char* b = a;

if (sizeof(a) != sizeof(b))
    printf("Marton.Kuzner no sabe de lo que habla\n");

La referencia no es el tutorial de un scener, es el estándar ISO. Un array NO ES un puntero. Un array NO ES INTERNAMENTE un puntero. Un array NO TIENE POR QUÉ estar en el stack. Un puntero NO TIENE POR QUÉ apuntar a memoria dinámica. Chico, ¿se pueden decir más barbaridades en un solo párrafo?

Esta también es gloriosa:

b = "chau"; //es equivalente a a = "chau";

Retiro lo dicho, nada de 1/8. Un cero como una casa.

Ah, se me olvidaba, si traduces o ayudas a traducir Thinking in C++ ya de paso te lo lees bien, es un buen libro.

Que se los explique paco

He de felicitar a paco por ser tan erudito en la materia, hubiera sido interesante que, dada su pomposa genialidad, hubiera sido él quien tratara de explicarle a manueldavid sobre la aritmetica de punteros (tema que no todo el mundo entiende a la primera). Llama la atencion que su enciclopedico conocimiento únicamente reluce para criticar mi explicación, pero no para instruir a usuarios que aún no lo habian captado. Lamento que mi intento de explicar en forma simple algo tan potente y complejo como los punteros resultara en una literatura tan "confusa" y "contradictoria". Supongo que la idea del reto era únicamente demostrar que uno es capaz de instalar el compilador, redactar la instruccion conflictiva y postear una transcripcion del resultado.

Sí, tal vez mis ejemplos no sean los mejores, incluso (por que no) que en el apuro algun caracter me haya olvidado (por que no admitir que, ademas de lo humano que soy, mi c esta muy fuera de lustre). Vamos, si lo unico que intente hacer fue explicar la aritmetica de punteros... ¿como lo habriais explicado vos?

no, arreglos y punteros no son exactamente lo mismo (de hecho, he tenido cuidado de no hacer creer que uno puede usar un arreglo como si fuera un puntero), pero no me pueden negar que no es por casualidad que (bajo ciertas circunstancias) uno pueda usar a punteros como si fueran arreglos y (como he aclarado, con limitaciones) viceversa. Que el compilador sea capaz de distinguir unos de otros y darles comportamientos específicos no alcanza para negar que internamente tengan una naturaleza común.
Solo he tratado de explicar que son equivalentes (que no es lo mismo que ser iguales). Sino, vean el punto 2.3 en http://www.lysator.liu.se/c/c-faq/c-2.html
Ademas, dado que el único argumento sobre la equivocacion de mi explicación es el funcionamiento del sizeof, por favor, invito a que explique a manueldavid por que "hola" + 2 equivale a "la" sin hacer ningun tipo de referencia a la aritmetica de punteros (dado que, por lo visto, es un mero cuento chino únicamente inventado por mí).

Respecto a la funcion sizeof, en la referencia incluida aclara que la funcion, al recibir un arreglo, el compilador modifica su comportamiento esperado para hacer que devuelva la cantidad de posiciones del arreglo. Pero si le pasamos un puntero nos devolverá el tamaño en memoria del mismo (no esperareis que el compilador adivine el tamaño del bloque asi por que si). Eso quiere decir que el compilador si distigue unos de otros, precisamente por eso sabe el tamaño del arreglo! Pero bueno, dado que mi referencia no es el estandar y que el sizeof("hola que tal") no es 4, todo esto debe de ser mentira...

Ahora, dado lo puritanos que son, invito a paco que incluya una referencia del estandar ISO que explique el comportamiento de sizeof (que sea distinto al que he expuesto) ó que incluso pruebe explicitamente cuan equivocado estoy.

De seguro Richie debe estar orgulloso de ver como la gente pierde el tiempo en vacuas discuciones, mientras que los novatos con interés son vulgarmente instruidos a programar con herramientas Microsoft. ¿En los foros de visual basic no hay discusiones como estas cierto? ¿Acaso serán actitudes como estas las que alejan a los novatos de lenguajes en serio como ensamblador o c? (si, antes que me juzgueis, sé que no es lo mismo asm que c)

Pero bueno, no perdamos el tema, me parece que nos hemos dispersado demasiado el thread original. Yo poseo 0 puntos en mi explicacion, ni siquiera he sumado con su version en Perl.

A ver paco, iluminanos, por que "hola" + 2 imprime "la" ?

A palabras necias, oidos sordos

Es evidente que no conoces el significado de reto. Para tu información no consiste en que lo acompañemos con la solución.

Francamente, baja ese tono o vete a patalear a otro lado, no consigues nada en este foro.

Imagen de cleto

Básicamente...

... me parece que te saltas una cosa muy importante. Todos los aquí implicados leímos tu respuesta con un tono de "sobradez", altivez o como quieras llamarlo. Y encima, después, vas y dices que Paco no tiene ni idea. Y ahora, no contento, sigues con el tono despótico sobre lo que sabe o no Paco. En fin, tú sabrás.

El reto (que es MUY MUY fácil y espero que ya lo tengas claro) habla sobre otros 7 programas más. Así que puedes explicar por qué crees que ocurre lo que ocurre en los demás lenguajes (si quieres, claro).

Las actitudes de las que hablas se aplican a personas que van de sobradas. Eso pasa en cualquier foro medianamente decente.

Un saludo!

Lo siento

Lamento mucho si mi actitud ha parecido sobradora, distante de ello. Simplemente me he molestado por que han tildado de absurda mi explicación argumentandolo con el sizeof... incisto... solo trate de explicar la aritmetica de punteros... tal vez me equivoque al expresar tan abiertamente que son lo mismo, cuando tecnicamente son equivalentes. Aun asi, no creo que decir que lo que he explicado es cualquier cosa.... que "... donde X es la dirección de memoria donde se guarda el primer elemento de la cadena. Pero eso no es verdad,..."... simplemente por que sí... hace tiempo que no uso c, pero eso no quita que el concepto que trate de explicar no sea válido y que arreglos y punteros no sean equivalentes. Hubiera apreciado si en vez de tildar de erróneo mi explicación, hubiese corregido las falencias semanticas que, posiblemente, no estaban puritanamente correctas.

No soy Richie, es mas, ustedes deben saber mucho mas que yo, solo que traté de explicar un concepto que hace único al lenguaje c... que lo potencia de forma extraordinaria y que hoy en día no es enseñado... hoy en día se prefiere enseñar a usar variants en visual basic.... total, ¿quien no tiene 2 gigas de memoria en su maquina? (trate de ser sarcástico)

Investigando

Lamentablemente, he de descargar un poco sobre el ejemplo citado de sizeof("hola"). Pueden buscar en referencias de c sobre el funcionamiento de la funcion sizeof y encontrarán que si la misma recibe como parametro un puntero (o un arreglo de caracteres, que convengamos es lo mismo) la función modifica su comportamiento esperado para intentar devolver el tamaño del arreglo especificado. MAS AUN, es el compilador el que busca el tamaño que hemos definido para el arreglo y reemplaza toda la expresión sizeof("hola") por su tamaño durante la compilacion (ni siquiera lo realiza en tiempo de ejecución)

Referencias:
http://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays#sizeof
y lamento incluir tambien el siguiente enlace
http://msdn.microsoft.com/en-us/library/4s7x1k91(VS.80).aspx

PD: Sin querer pasar por ignorante (dado que por lo visto ya lo he hecho) acaso el comportamiento de C es distinto al de C++ ??

Lo dicho, estudia

No, en C++ es distinto. Hay sobrecarga de operadores. Por tanto el resultado no está definido.

Imagen de david.villa

Hombre, se supone que el

Hombre, se supone que el ejemplo es con C++ estándar, sin ningún operador raro definido. Si no vaya historia.

No soy portavoz de ningún colectivo, grupo o facción. Mi opinión es personal e intransferible.

¿Por qué se supone?

Para el ejemplo de C++ se tiene que suponer:

  • Que hay un include de iostream en algún lado
  • Que hay un using std en algún lado
  • Que hay un main que contiene la expresión

¿Y me dices que se supone que no se supone nada más? Hombre...

Imagen de david.villa

Lo imprescindible para que

Lo imprescindible para que funcione digo yo. Si me descuelgo ahora diciendo que había definido un operador+ que lanzaba un misil ICBM contra la estatua de la libertad sería complicado que alguien lo acertara. Seamos retorcidos, pero sin pasarnos Smiling. En cualquier caso, admito que la posibilidad del operador es interesante puesto que no puedes asegurar que ese código imprimirá SIEMPRE "la".

PS: Nada como la polémica para reavivar el reto Sticking out tongue.

No soy portavoz de ningún colectivo, grupo o facción. Mi opinión es personal e intransferible.

Ups...

Lamentablemente no me exprese correctamente, lo siento. Simplemente observe que a algunos le costaba entender la aritmética de puntero asi que traté de explicarla suponiendo que podian imaginar un X que representa la dirección de memoria de una variable (siendo X distinto de la variable, asi como "int a" es distinto de "int *a")... reitero, lamento no haberme expresado con la claridad suficiente, pero en su momento me parecio importante tratar de explicar ese concepto para que puedan entender como afectaba a la interpretación la suma del numero 2.

Por otra parte, si sirve para tener algo mas que un octavo de la respuesta, en perl la misma expresión se evalua de forma distinta, resultando en "2". Dado que perl tiene un operador distinto para la suma que para la contatenacion, al utilizar el operador + intenta sumar numericamente "hola" y 2, y dado que no logra interpretar numero alguno del "hola", le asigna un valor de 0, resultando en 0 + 2 = 2

Imagen de david.villa

Por aclarar la cuestión... la

Por aclarar la cuestión... la pregunta es: ¿Por qué esto imprime 5 en lugar de 4 como en principio parece que debería ser?

printf("%d", sizeof("hola"));

No soy portavoz de ningún colectivo, grupo o facción. Mi opinión es personal e intransferible.

Por que es un arreglo de 5 posiciones

la respuesta de sizeof("hola") es 5 debido a que esta compuesto por 5 caracteres, los 4 del hola y uno adicional por el finalizador de cadena (o /0)

Joe, no pillas una

Te está preguntando que por qué imprime el tamaño del array en lugar del tamaño del puntero, porque según tú son equivalentes. Vamos, que podía haberlo escrito así: ¿Por qué sizeof("0123456789") es 11 en lugar de 4 como parece que debería ser según tú?

¿No será que un array y un puntero no son la misma cosa? ¡Aaaaaahhh! ¡Magia!

En Ada 95?

El acceso a la consola en Ada 95 es mucho menos "listo?" "simple?" "ambiguo?" ya que debes indicar explícitamente qué tipo vas a imprimir.

PD: Ada.Text_IO.Put("Hola"+2); no compila Smiling

Félix Jesús Villanueva Molina
felix.villanueva(esto es una arroba)uclm.es

No todos son comparables...

Interesante. ¿Se ve el interés de C# por parecer otro Java?

System.Console.WriteLine no es lo mismo que los otros, debería usarse System.Console.Write a secas. Y el de c-shell no entiendo qué se pretende. Si es por usar el operador '+' tienes que meter la expresión en un if, un while o un exit. Y si no, esto podría ser tanto csh como Bourne sh, bash, dash, ksh, tcsh.

Imagen de david.villa

Claro que son son comparables

De eso se trata, Que aunque en apariencia debíeran dar el mismo resultado, el operador '+' en la versión C no tiene nada que ver con el de la versión C#, Java o Python. Mientras en el de C es aritmética de punteros, en el de Python estás invocando un método... Esa es la intención del reto, tener una visión más horizontal de como tratan los distintos lenguajes algo tan tonto como una "suma" de cadenas.

No soy portavoz de ningún colectivo, grupo o facción. Mi opinión es personal e intransferible.

Imagen de manueldavid

¡Esto es cosa de brujería,

¡Esto es cosa de brujería, seguro!, no me he podido resistir probarlo en C y en C++, ¡dios!, ya he leído que lo de "qué imprime" se puede considerar una pregunta retórica, pero vamos igual que a vosotros supongo que el programa sólo os imprime:

$ la

¿Por qué?

No lo entiendo, seguiremos investigando.

No sueño con grandes palacios, no sueño con grandes lujos, no sueño con grandes poderes, porque yo sólo sueño con grandes sueños

Imagen de cleto

Te voy a dar una pista...

... creo que el siguiente código te aclarará aún más:

printf("Hola" + 8);

Smiling

Si, si, eso aclara bastante...

A mi me gusta más así:

printf(&2 ["hola"])

Es más claro todavía Smiling

Imagen de manueldavid

Supongo que instrucciones

Supongo que instrucciones como estas:

printf("hola"+2);

o estas:

printf(&2 ["hola"]);

lo que hacen es imprimir a partir del carácter indicado por el número (parece que no hace falta ser un lince para darse cuenta Sticking out tongue ). Pero lo cierto es que no sé por qué, nunca lo había visto así ..., tendré que viajar más Smiling .

Seguiremos investigando.

Saludos.

No sueño con grandes palacios, no sueño con grandes lujos, no sueño con grandes poderes, porque yo sólo sueño con grandes sueños

Elemental mi querido watson

La respuesta a por qué es que para "hola" + 2 la respuesta es "la" se justifica precisamente en la aritmética de punteros.

La constante "hola" (constante debido a que la hemos fijado en el código) durante la ejecución del programa se encuentra almacenada en una dirección de memoria. Llamemos a esta dirección X... entonces, debido a que una cadena de caracteres (o string, como quieran llamarla) es un arreglo de caracteres individuales (chars para los adeptos al c, bytes para los que entienden de cualquier forma), podriamos decir que el valor de la posicion X es "h", de X+1 es "o" (la letra subsiguiente a la "h") y así sucesivamente encontraríamos "l" en X+2; "a" en X+3 y el terminador de cadena (/0) en X+4. Teniendo esto en claro, la expresion "hola" + 2 es evaluada de la siguiente forma: teniendo la constante "hola", a su respectiva dirección sumarle 2 (2 bytes, debido a que es un arreglo de chars). Así, el programa se desplaza 2 posiciones y evalua lo que encuentra a continuacion como una cadena de caracteres (nótese que la respuesta es "la" y un terminador de cadena)

Respecto a la infame sentencia "hola" + 8... dado que 8 supera el tamaño de la cadena, el programa evaluará el contenido de la memoria ocho posiciones mas atras de la palabra "hola" y de su terminador. A tal efecto, debido a que no podemos asegurar en que lugar de memoria será almacenada la constante "hola" original, ni que otras variables se gestionarán junto a dicho espacio de memoria, es factible considerar que dicha instrucción interpretará como cadena de texto la basura que rondea en memoria a la constante declarada, buscando como finalización de dicha cadena el proximo caracter finalizador (/0).

Dado que son tan ingeniosos, ¿por que no consideran los efectos de la expresión "hola" - 5 ??

Imagen de cleto

Gracias...

... por lo de ingeniosos. Como autor infame, baste decir que lo del "hola" - 5 me parece un reto interesante. Me da miedo porque restar 5 a la cadena "hola" supongo que el resultado será decir 5 veces hola para adentro.

Aún así, me he atrevido a probarlo y esta ha sido mi salida:

mi_salida_de_mi_programa_de_prueba

Creo que hay algún "hola" de más. Supongo que será por VoiceOverFlow.

Un saludo!

Imagen de david.villa

respuesta más o menos

respuesta más o menos correcta (y larga) para la versión de C. ¿Qué hay de las demás?

PD: ¿Eso te parece ingenioso? Pero hombre, si es un ejercicio para parvulitos.

No soy portavoz de ningún colectivo, grupo o facción. Mi opinión es personal e intransferible.

y que hay de la respuesta en python??

a todas estas, python no imprime nada, salvo un error que dice: TypeError: cannot concatenate 'str' and 'int' objects,
no soy muy erudito programando, en realidad me intriga mucho el tema por que a ilustrado muchas dudas..les agradeceria mucho den las explicaciones referentes a los demas lenguajes de programacion

Si NO es libre, NO existe