C++/CLI (II): Sobre referencias y referencias de seguimiento (tracking references)

En C++ , cuando queremos que una variable sea modificada dentro de un método tenemos dos opciones: pasar su dirección de memoria y operar dentro del método con el puntero, o utilizar referencias.


Aunque en un principio las referencias y los punteros pudieran parecer equivalentes, no lo son, ya que existen diferencias bastante notables. Pero vayamos por partes.


Veamos el siguiente código:











void CambiaA(int *b)


{


(*b)++;


}


int main(void)


{


int a=5;


CambiaA(&a);


printf(«%i»,a);


return 0;


}


void CambiaA(int& b)


{


b++;


}


int main(void)


{


int a=5;


CambiaA(a);


printf(«%i»,a);


return 0;


}


Observamos que el código es casi idéntico. El bloque de la derecha trabaja con referencias, el de la izquierda con punteros, y ambos realizan la misma acción: sacar por pantalla el número 6, que se corresponde de instanciar una variable que llamamos a (es decir, crear un hueco en la pila de suficiente tamaño para guardar un entero) y guardar en su interior el valor 5. Tras la llamada al método, el contenido de a se incrementa en uno, pero mediante diferentes vías (el hecho de que un compilador serio de C++ generara prácticamente el mismo código no nos interesa, lo que nos interesan son los conceptos subyacentes).


El código de la derecha, aparte de ser más claro, es más económico en memoria (aunque posiblemente no en tiempo de compilación). Cuando entramos en CambiaA(), el compilador no crea ninguna variable nueva, sino que anota dónde está a en la pila y, al ejecutar la instrucción b++ incrementará directamente la casilla en donde se ha guardado a, aunque ahora se llame b (Otra vez queremos hacer notar que lo que realmente está ocurriendo es que el compilador cogerá de la pila el valor de a, lo meterá en un registro del micro, realizará el incremento y volverá a colocarlo en su lugar, pero repetimos que de momento sólo nos interesa el concepto).


En el código de la izquierda, la entrada en CambiaA() creará una nueva variable en la pila que es el puntero b, cuyo contenido será la dirección de memoria en donde esté guardado a. Y cuando incrementemos el valor de *b, estamos realmente mirando dónde apunta b y cambiando dicho valor.


La diferencia es sutil pero muy importante. En este ejemplo puede no verse claro, pero si el lector utiliza sobrecarga de operadores podrá comprobar cuán potentes son las referencias a la hora de trabajar con estas construcciones, ya que mediante su uso permiten devolver una referencia a la misma variable, ahorrando así memoria y acelerando las cosas.


Un consejo práctico a la hora de elegir qué utilizar, si un puntero o una referencia, es hacernos la pregunta de si la llamada al método que va a modificar el parámetro trabaja con asignación de memoria dinámica o no; es decir, si lo que estamos pasando está instanciado en el montículo, lo suyo es pasar un puntero, y si está instanciado en la pila, usaremos referencias. Evidentemente un es una regla estricta, sino simplemente un mero juicio de valor ante la duda.


Un uso práctico para las referencias es la devolución de resultados. Supongamos que queremos realizar una operación matemática cuyo dominio en el resultado puede ser cualquier valor de la variable a considerar, por lo que no podemos determinar a priori si el resultado obtenido es ese porque la operación se llevó a cabo satisfactoriamente o porque el cálculo se detuvo ahí. Podríamos utilizar una firma de método como la siguiente:


bool OperacionMatematica(Elemento &e);


De modo que la devolución de true nos indica que lo que hay en e es válido, y en donde Elemento puede ser cualquier construcción matemática (Aquí entramos en otro tema que genera bastantes discusiones, y es la decisión de lanzar una excepción en caso de error o devolver un valor como acabamos de hacer, pero no vamos a discutir eso ahora).


Esta característica también está disponible en C++/CLI con el nombre de referencia de seguimiento (o tracking reference en inglés). El concepto es el mismo, aunque la nomenclatura y sintaxis sean diferentes.


En C++/CLI una referencia se indica mediante el símbolo %, y su funcionamiento es básicamente el mismo. Realizando el código anterior en C++/CLI quedaría:











void CambiaA(int ^b)


{


^b++;


}


int main(array<String ^>^)


{


int a=5;


CambiaA(&a);


Console::WriteLine(a.ToString());


return 0;


}


void CambiaA(int% b)


{


b++;


}


int main(array<String ^>^)


{


int a=5;


CambiaA(a);


Console::WriteLine(a.ToString());


return 0;


}


Si observamos, los cambios son meramente cosméticos y estamos realizando las mismas acciones. Ahora disponemos en el código de la izquierda de referencias (en su equivalente al puntero nativo) y en el de la derecha de referencias de seguimiento (en su equivalente a la referencia nativa). Ya sé que la nomenclatura es un poco liosa al llamar referencia al manejador para las variables situadas en el montículo manejado y referencia de seguimiento al simple alias, pero es lo que hay.


Pese a lo que pudiera pensarse con el código de la izquierda, no hay ningún encajamiento ni desencajamiento, ya que al tener almacenada a en la pila, la llamada a CambiaA() simplemente modifica su valor. Vea si no el código MSIL generado para dicho método:



Pero vayamos un paso más en cuanto a C++/CLI. ¿Podemos pasar una referencia de seguimiento de una referencia? Pues claro que sí. Igual que en C++ podemos pasar la referencia de un puntero. Veámoslo.











using namespace System;


void CambiaSTR(String^ %str)


{


str=«Hola Nuevo»;


}


int main(array<String ^>^)


{


String ^cad=«Hola Viejo»;


CambiaSTR(cad);


Console::WriteLine(cad);


return 0;


}


void CambiaA(int* &b)


{


(*b)++;


}


int main(int argc, _TCHAR* [])


{


int *a=new int();


*a=5;


CambiaA(a);


printf(«%i»,*a);


return 0;


}


Aquí el bloque de la derecha volverá a devolver 6 como respuesta y el de la izquierda «Hola Nuevo», quedando la cadena «Hola Viejo» marcada para destrucción («Hola viejo» es una cadena estática y está alojada dentro del ejecutable, en C++ simplemente no pasaría nada al perder la asignación de cad, pero en C++/CLI quizás la cadena se copie del segmento de datos al montículo manejado durante la carga del ensamblado. Realmente ignoro el comportamiento. En otro momento lo miraré).


Y cómo no, no es necesario llamar a un método o función para trabajar con las referencias:











using namespace System;


ref class Cosa


{


public:int a;


};


int main(array<System::String ^> ^args)


{


    Cosa ^c1=gcnew Cosa();


    c1->a=30;


    Cosa %c2=*c1;


    c2.a++;


    Cosa ^c3=%c2;


    c3->a++;


    Console::Write(c3->a.ToString());


    return 0;


}


class Cosa


{


public:int a;


};


int _tmain(int argc, _TCHAR* argv[])


{


    Cosa cosa;


    cosa.a=33;


    Cosa &rCosa=cosa;


    rCosa.a++;


    printf(«%i»,cosa.a);


    return 0;


}


Un tema curioso a observar en el bloque de C++/CLI (el de la izquierda) consiste en cómo desreferenciamos una referencia sobre una referencia de seguimiento. Me refiero a la línea


Cosa %c2=*c1;


Si miramos con detalle, estamos haciendo exactamente lo mismo que con el código nativo cuando desreferenciamos un puntero a una referencia, lo que nos permitirá realizar plantillas que puedan trabajar indistintamente con objetos manejados o nativos.

TIP: Instalar cualquier SDK de Windows CE 5.0 en Vista

Justo esta mañana me he dado en los dientes con una piedra bien gorda. De nuevo vuelvo a la zanja del Windows CE 5.0 (mis primeras entradas en esta bitácora tienen algunas entradas sobre él), para actualizar algunas cosillas antiguas y certificar nuestros productos para cierta placa que corre una versión muy modificada de dicho sistema operativo (tan modificada que se ha sustituido el GDI por uno propio, se ha eliminado casi todo el USER.DLL, y el arranque es completamente nuevo –y diferente). Está tan modificado y recortado que mientras una imagen más o menos normal suele ocupar unos 14 MBbyte, la nuestra con lo necesario para depurar ocupa 2.4 MByte y la final se puede reducir hasta 1 MByte. 


Como dice mi jefe, «hacer los drivers» para nuestros productos. Y como digo yo, «hacer un par de ficheros .cpp y .h» con el funcionamiento de cada uno de nuestros productos y entregarlos en código fuente.


Pero la primera en la boca: Visual Studio 2005 bajo Vista se niega a conectarse con la placa a través de Ethernet (Hace como un siglo que ya no lo hacemos mediante ActiveSync y/o RS-232 –Demasiado lento). Bajo Windows XP sí que se conecta sin problemas.


Luego la segunda: No se puede instalar el SDK construido con el Platform Builder 5. Bueno, sí se instala pero como si no lo hiciera, ya que el Visual Studio no da la opción para crear/manejar proyectos que correspondan al SDK instalado.


Solucionar la primera ha sido relativamente sencillo. Se cogen los ficheros existentes en «%ProgramFiles%Common FilesMicrosoft SharedCoreCon1.0Targetwce400<micro> dentro del ordenador que está ejecutando Windows Vista y Visual Studio 2005 con el parche para Vista.


Como para disponer de un sistema de conexión via Ethernet con el Visual Studio 2005 es necesario ejecutar esos ficheros de forma remota, en nuestro caso hemos modificado el proceso de construir la BSP (el NK.BIN que contiene el sistema operativo que luego se grabará en el aparato de destino) para que integre dichos ficheros.


Es por ello por lo que hay que copiarlos al lugar de donde quiera que los coja el Platform Builder para generar la imagen. En mi caso se trata de una máquina virtual, ya que ni el Vista ni el XP se llevan muy bien con el PB5.


Repetir este paso me ha servido también para actualizar a Mayo del 2007 los parches del CE y del Platform Builder (la última fue en Enero del corriente).


Primera solución: tomando dichos ficheros e integrándolos dentro de la imagen binaria en el mismo lugar que antes integraba los del Visual Studio 2005 SP1 ejecutando sobre XP ya puedo conectar desde Windows Vista.


La segunda ha sido un poco más delicada, pero de momento está funcionando bien. Al parecer si se tiene activado el UAC hay un script dentro del instalador del SDK que falla sin avisar y que no registra el nuevo SDK instalado. Y no vale ejecutarlo como administrador.


La solución es sencilla, y tras una navegación (y gracias a Tío Google) más o menos infructuosa uno de los chicos de Microsoft nos da la solución, no sólo la que me ha funcionado a mí, sino otras muchas soluciones a problemas con Windows Vista y Windows CE 5.0. La entrada es esta. No tiene que ver exactamente con lo que estoy hablando, pero dado que Windows Mobile 5.0 no es más que un Windows CE 5.0 muy modificado (justo como el mío, pero en sentido opuesto), sirven para cualquier SDK.


Segunda solución: desactivar el UAC, reiniciar Windows, instalar el SDK y volver a activar el UAC.

C++/CLI (I): Punteros y referencias

De montículos, pilas y asignaciones
De todos es conocida la existencia de dos almacenes de memoria para el uso de nuestros programas. Por un lado tenemos la pila y por el otro el montículo. En la pila se colocan las variables automáticas (sí, lector, no te extrañes de ese nombre: una variable automática es aquella que definimos y declaramos de forma directa, es decir int a declara una variable automática con el nombre de a). Y en el montículo las variables indirectas o de asignación dinámica.


Tradicionalmente Windows pone a disposición para cada programa una pila y tres montículos, a saber, el montículo local, el global y el virtual (no vamos a entrar en detalles, pero el lector inquieto podría echar un vistazo a las funciones del API de Win32 VirtualAlloc(), GlobalAlloc() y LocalAlloc() para comprobarlo).


Una aplicación .NET añade dos estructuras de memoria más, es decir, tanto una pila manejada como un montículo manejado. Ambos están situados y controlados dentro de la máquina virtual .NET, y generalmente son los que el programa va a utilizar siempre que no ejecute código nativo mediante Interop de atributos o de IJW.


Quizás al programador de C# le llame la atención la separación entre pila manejada y pila nativa, pero así es en la realidad. En C++/CLI, utilizando el Interop IJW, podemos colocar conjuntamente ambos tipos de variables sin ningún problema, pero cada una irá a su pila, es decir, en el fragmento de código


void fnc(void) {
char *pCad;
StringBuilder ^s;


la variable pCad irá almacenada en la pila nativa y s lo irá en la manejada. Y cuando hagamos


pCad=new char[20];
s=gcnew StringBuilder();


el hueco para contener a pCad irá al montículo nativo y el correspondiente hueco para s se reservará en el montículo manejado, y se asignarán sus direcciones respectivas al contenido de ambas variables.


Describir ambas pilas no tiene mucho sentido ya que ambas son casi equivalentes salvo que una la controla el motor .NET y la otra el sistema operativo, y su funcionamiento es idéntico: guardar los puntos de retorno de los métodos y las variables automáticas. La única ventaja de la nativa es que tiene un área especial para almacenar variables globales, que no está presente en su contrapartida manejada.


Los montículos sí que son enormemente diferentes. El nativo no es más que un saco de memoria física asignada al espacio de direcciones de la aplicación, mientras que el manejado es otra cosa mucho más delicada y potente: puede controlar desbordamientos, olvidos en la liberación de bloques, y se compacta para hacer sitio a nuevos bloques.


Punteros y referencias
pCad es un puntero, s es una referencia. ¿Cuál es la diferencia? El espacio reservado al que apunta el primero va en el montículo nativo, y el del segundo en el manejado. Dicho así, y habiendo leído el párrafo anterior casi lo tenemos todo.


Pero veamos algunos detalles. Como pCad contiene una dirección de memoria física, podemos cambiar su valor sin problemas. No me refiero a cambiar a lo que apunta pCad, sino a cambiar el contenido del propio pCad. Ni el compilador ni el entorno de ejecución nos dirán nada. En el segundo ejemplo hemos asignado en el montículo 20 bytes, por lo que es perfectamente válido hacer


*(pCad+10)=’a’;


Simplemente estamos cogiendo lo que hay en pCad, le sumamos 10 y escribimos en la dirección de memoria resultante la letra ‘a’.


Eso, en .NET, no se puede hacer porque, siguiendo con el ejemplo, s no es un puntero, sino una referencia. No contiene una dirección de memoria física, sino un índice dentro de una tabla que es interna al motor de tiempo de ejecución del .NET y que describe los bloques de memoria asignados dentro del montículo manejado. Como poco hay una doble indirección, es decir, para acceder al contenido de s tenemos que, primero buscar su valor dentro de dicha tabla, y luego mirar a dónde realmente está apuntando. Pero eso no lo hacemos nosotros, lo hace el propio .NET.


Las ventajas de este sistema son evidentes. No podemos salirnos, si intentamos escribir fuera de rango el entorno de ejecución nos avisará. Si nos olvidamos de liberar el bloque, cuando s salga de ámbito (es decir, el valor almacenado dentro de s deje de existir porque haya sido eliminado de la pila), el recolector automático de basura entrará en marcha y liberará el bloque que ahora ha quedado huérfano.


Estas dos cosas no se pueden realizar con un puntero. Si el contenido de pCad se pierde, hemos eliminado la opción de recuperar el bloque, ya que el valor perdido es el que le dice al sistema qué tiene que liberar. Y escribir fuera es completamente trivial (y potencialmente catastrófico).


¿Qué es más interesante? Desde mi punto de vista, las referencias. Añadimos una indirección extra y posiblemente algo más de sobrecarga, pero eliminamos los dos errores más temidos de un programador de C++: olvidarnos de liberar recursos y sobreescribir fuera de rango.


Proxyes
La mayor limitación en esto es que no tenemos elección sobre qué usar. Es decir, si trabajamos con objetos .NET (C++/CLI) tenemos que forzosamente utilizar referencias. Y si trabajamos con elementos nativos (C++) sólo podemos usar punteros.


Hasta que los chicos de Microsoft no se decidan a implementar en el lenguaje referencias nativas y punteros manejados (cosa que Herb Sutter ha citado alguna vez como posible), tenemos que trabajar así.


Pero existe una forma para poder hacer lo del párrafo anterior y, aunque es ineficiente, es posible. Y es la utilización de Interop mediante objetos proxy. En otro momento hablaremos de ello (más o menos cuando salga Orcas, que trae algo sobre el tema).


Punteros interiores
Pero no todo dentro del mundo manejado son limitaciones a la hora de manejar referencias. En cierta medida las podemos controlar como punteros… siempre y cuando no nos salgamos del objeto.


Es decir, podemos tener un puntero interior al interior de un objeto, y podremos trabajar con él de forma idéntica a los punteros siempre que no nos salgamos del interior del mismo.


Quien quiera ver algo por su cuenta, aquí y aquí tiene referencias sobre cómo operan los punteros interiores. También puede esperar a que ponga alguna entrada sobre ellos aquí.

Futuras Entradas

Como en todo serial radiofónico que se precie, es de rigor mostrar en unas breves pinceladas lo que depara el futuro de una obra, para impactar al oyente y que no piense que a los autores se les ha acabado la imaginación.

También hay otro motivo, y es para que no olvidéis a qué está destinada esta bitácora. No es para instruiros. No es para lucir mis conocimientos. No es para avisar de las cosas que me pasan en mi devenir de chafateclas impertinente e impenitente. No está destinada a nada de eso.

Quien realmente lo piense así se equivoca. Del todo. Esta bitácora sólo tiene un motivo: forzar a su autor a estudiar, a estar más o menos al día en lo que le interesa y a anotar esas cosillas que le pasan para no volver a golpear la misma piedra dos veces.

Pero como todo gañán que se precie, si no se compromete públicamente, al final termina tumbado en su sillón de leer, absorbiendo novelicas de ciencia ficción y haciendo sudokus, como dice mi madre. Y aun comprometiéndose públicamente…

Bueno, al tajo.

Estoy preparando (en la mente, pero preparando) una serie de artículos sobre C++/CLI. El tratamiento va a ser parecido al que hice sobre el C# pero con mayor profundidad. Tras haber hecho varios proyectos utilizando este lenguaje, y con cierta ayuda de fuentes varias, el autor se considera lo suficientemente capacitado (hay que ver lo descaradamente pagados de sí mismos que son algunos) como para meter la cabeza de lleno en ello. El primero de todos será una comparación entre punteros y referencias, qué son, por qué son y cómo funcionan. En el segundo seguro que hablo de cajas.

Otra serie es la de los tips y bloques de código enseñando cosas curiosas, como ya he publicado alguno. Estos van a ser los menos –no porque tenga pocos-, sino porque generalmente están asociados a temas que se salen de ámbito.

La tercera y que seguro va a levantar alguna ampolla, como ya ha hecho con algunas entradas anteriores, va a ser el tema de los bugs tanto del .NET como del propio Visual Studio. Desde el último que puse he ido coleccionando alguno más, he afinado los existentes y también he recibido feedback de Connect sobre los que he puesto allí. Quizás no sean fallos propiamente dichos, quizás sólo sean características peculiares del entorno o de la plataforma, pero esas cosas raras están ahí y en su justa medida debemos airearlas. La primera entrada va a ser muy bonita, ya veréis qué bonito es vaciar una ficha llena de controles sin tocar para nada ni el diseñador ni la parte de InitializeComponents. En otra lanzaremos excepciones que simplemente cerrarán la aplicación sin mensaje alguno. Y a ver si consigo de una puñetera vez tumbar la VM .NET con un ejemplo en lugar de con la aplicación completa (que no puedo mostrar). Nos vamos a divertir.

Estoy preparando en otro lugar una serie de articulillos sobre PowerShell (ya sabéis, la nueva consola de Windows para administradores). También los pondré aquí conforme vayan siendo publicados en los grupos de Tella.

Resumiendo, cuatro tipos de entrada que llevarán los siguientes prefijos:

  • «C++/CLI (<número>):»
  • «Bugs:», aunque no todo van a serlo, pero sí serán cosas raras.
  • «PowerShell (<número>):».
  • «Tips:»

Las series de bugs y de tips no llevan número porque no van a estar seriadas. Cualquier otra entrada que ponga y que no tenga que ver con estos temas irá sin prefijo.

Bueno, pues eso es todo. Esperen y lean.

De jaquers y otras yerbas

El Tendero Digital cierto día me llevó al Otro Lado del Mal. Pero que nadie piense de forma errónea. Lo primero es un blog que se llama Al otro lado del mostrador, y no es más que la visión de un vendedor de informática –por cierto, la tienda está en un pueblo al lado del mío, o eso he creído adivinar-. Lo segundo es otro blog de similares características, pero de un corte más variopinto y, para qué engañarnos, algo más salvaje. Lo mismo me equivoco, pero estoy casi seguro de el primer blog me llevó al segundo, aunque ahora no encuentro la entrada correspondiente.

Pues bien, el otro día el Maligno publicó una entrada que me llamó la atención. Habla sobre el concepto de hacker y para comprender esta entrada mía, antes debes leer aquélla.

¿Ya? Bien, seguimos.

Trabajo para la filial española de un grupo multinacional que es líder en su área de mercado. Es tan líder que es el único que hay de su tamaño. También trabajo para su departamento principal de desarrollo situado en Holanda, pero desde casa. Y a veces sufro atisbos de lo que se cuece al otro lado del charco, aunque no suelo estar muy al loro.

Pero sí que tenemos una palabra para designar al hacker del que se habla en la entrada anterior, y encima sin problemas con los colores o adscripciones políticas.

La palabra es gurú, o guru como ellos dicen (que pronuncian gúru, acentuando la primera u). En su –nuestro- concepto, un gurú es aquella persona que no tiene superiores en su área de conocimiento. Podrá tener iguales, pero nunca superiores. Por ejemplo, mi jefe es uno de esos gurús internacionalmente reconocidos dondequiera que vaya y hable con quien hable.

Otra ventaja de ser un gurú y no un hacker es que no necesariamente has de serlo de la informática (por ejemplo mi jefe, que sabe un mazo de ordenadores para ser un jefe de su nivel, es un gurú, pero de otra cosa).

Otro ejemplo más cercano. Stroustrup es un gurú del C++. Y Sutter del C++/CLI y posiblemente también del C++. Y uno puede ser un gurú de reventar Webs.

Entonces, quitamos el color y el sabor al sustantivo y lo aplicamos al adjetivo (o como quiera que se diga ahora, ya se sabe que las formas de nombrar al lenguaje cambian cada cierto tiempo). Tendremos, pues, un gurú de algo, sea ese algo bueno o malo.

Por lo tanto, propongo cambiar (o mejor, añadir) el significado tradicional de la palabra hacker a la de gurú, y modificar el significado de la primera, así como su grafía.

Por ello, propongo, también, las siguientes modificaciones al término hacker:

  • Juasquer o Juascker: dícese del individuo de cualquier edad y autoproclamado hacker que cualquier otra persona (una maruja o un mecánico de coches, por ejemplo) automáticamente detecta que no tiene ni puñetera idea de lo que está hablando. Es un tipo de hacker muy habitual. El hecho de anteponer la partícula juas a la palabra indica las carcajadas con las cuales suelen ser recibidas sus afirmaciones.
  • Juaquer o Juacker: dícese del individuo preadolescente o adolescente y autoproclamado hacker que, basándose en cualquier documento bajado de internet, estudiado y apenas entendido, es capaz de realizar alguna tarea no habitual, como usar un Proxy Socks, borrar ciertos cookies de su navegador y cosas similares, aunque proclame saber acceder a la Web del Pentágono pero no te lo dice porque es muy peligroso. Suelen sentirse orgullosos de usar el Firefox o el Thunderbird porque no tienen fallos. NOTA: Si el juaquer aparenta tener cuarenta tacos no importa, sigue siendo un preadolescente descerebrado que ha crecido en cuerpo pero no en mente.
  • Jaquer o Jacker: dícese de la persona de cualquier edad y autoproclamado hacker que, utilizando una verborrea más o menos técnica, generalmente sacadas de webs y revistas de tirada general, es capaz de engañar a la gente no experta. Por ejemplo, un jacker se jactará de haber hecho un compresor utilizando el algoritmo Lempel-Ziv con un RLE progresivo mezclado con unas tablas hash de longitud variable que, siempre, siempre, comprime al 50% cualquier fichero, incluso uno ya comprimido con su utilidad. Cuando le preguntas por el descompresor te dice que está en ello pero que tiene ligeros problemas con el algoritmo inverso del RLE, pero que está en ello y pronto lo tendrá.

Y ahora los adjetivos, es decir, una palabra más que califica al individuo basándose en ciertos complementos:

  • <cualquiera de las anteriores> blanco: Dícese de aquel que, entrando en una de las categorías anteriores, suele ir más o menos limpito y oliendo a lavanda.
  • <cualquiera de las anteriores> negro: Dícese de aquel que, entrando en una de las categorías anteriores, suele ir más guarro que la Parrala, con un olor corporal inaguantable y con una nube de mosquitos y moscas rodeándole la cabeza.
  • <cualquiera de los anteriores> neutro: Dícese de aquel que, entrando en una de las categorías anteriores, una veces es negro y otras blanco. También puede aplicarse a aquel que, pareciendo chico es chica y viceversa.
  • <cualquiera de los anteriores> político: Dícese del subnormal profundo que, encima de ir por la vida haciendo el fantasma y el tonto, mezcla el tocino con la velocidad, se mete en camisa de once varas y aspira a ser nombrado <mejor no lo digo>.

Bueno, y eso es todo.

Espero que se tomen la primera parte de esta entrada en serio y la segunda en broma pero con cierto tono irónico. Y recuerden: un gurú o un hacker de verdad nunca se autoproclama como tal, sino que conforme va caminando por la vida los demás lo señalan con el dedo y dicen de él: «ahí va el gurú Pepito».

Novedades: MSDN Magazine y F#

MSDN Magazine
Ya está online el nuevo número de junio de la MSDN Magazine con algún artículo de interés para los programadores de C++. La revista se puede acceder en castellano desde aquí.

El artículo de interés es C++: Una mirada desde adentro a la próxima generación de Visual C++, que ya apareció en un blog de Microsoft en inglés, pero que ahora se puede disfrutar en el idioma de Cervantes.

También se inicia una nueva serie sobre C++/CLI dentro de la sección Netting C++, cuyo primer artículo se titula EEK! Introducción. Según el autor se trata de la creación de una aplicación paso a paso para enseñar el lenguaje C++/CLI. Pero ojo, que la aplicación consiste en

¡un entorno simulado de una jaula con un ratón!

Promete ser muy, pero que muy interesante.

Lenguaje F#
Creo que algún bloguero de por aquí ya ha comentado algo sobre el citado lenguaje, pero el buscador no me devuelve ninguna entrada, así que no puedo poner ninguna referencia.

F# es un lenguaje mixto funcional, imperativo y orientado a objetos. Esta nueva versión trae compatibilidad con los demás lenguajes .NET, acceso al .NET Framework, un compilador de línea de comandos, integración completa con Visual Studio 2003 y 2005 y una consola de comandos interactiva, imagino que al estilo de PowerShell.

No lo he probado ni creo que tenga tiempo para hacerlo, pero a quien le interese, puede bajarlo desde aquí.