<?xml version="1.0"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">
   <channel>
      <title>David Capello</title>
      <description>Feeds de los blogs de esta persona, desconocida por todos (hasta por el mismo).</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=lP8f3hnf3BGlYcsNj0nRlg</link>
      <pubDate>Thu, 29 Jul 2010 14:34:04 -0700</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <item>
         <title>Tentación</title>
         <link>http://davidcapello.blogspot.com/2010/07/tentacion.html</link>
         <description>&lt;div class=&quot;separator&quot; style=&quot;clear:both;text-align:center;&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://1.bp.blogspot.com/_LUOxBrR4np4/TE-Dmo-xf8I/AAAAAAAAAgQ/fW86Ecuh1rU/s1600/GoogleChrome.png&quot; style=&quot;clear:left;float:left;margin-bottom:1em;margin-right:1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://1.bp.blogspot.com/_LUOxBrR4np4/TE-Dmo-xf8I/AAAAAAAAAgQ/fW86Ecuh1rU/s320/GoogleChrome.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;A veces siento que me mira y me habla... y escucho &lt;i&gt;&quot;vení, haceme click, dale ;) ... tengo un montón de cosas para ofrecerte&quot;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Al final, siempre me defrauda.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-7896907810988264843?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-7896907810988264843</guid>
         <pubDate>Tue, 27 Jul 2010 15:13:00 -0700</pubDate>
         <media:thumbnail width="72" url="http://1.bp.blogspot.com/_LUOxBrR4np4/TE-Dmo-xf8I/AAAAAAAAAgQ/fW86Ecuh1rU/s72-c/GoogleChrome.png" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Apuntes y creatividad</title>
         <link>http://davidcapello.blogspot.com/2010/07/apuntes-y-creatividad.html</link>
         <description>Consejo: Si vas a enseñar una materia en la facultad o un curso, ¿por qué no agregarle un poco de creatividad al asunto? En vez de usar los mismos ejemplos del libro de referencia, a veces es bueno inventar otros (inclusive, evitar usar una escaneada del libro puede ser una buena idea).&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-857809327235346336?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-857809327235346336</guid>
         <pubDate>Tue, 27 Jul 2010 12:06:00 -0700</pubDate>
      </item>
      <item>
         <title>Interfaces gráficas interesantes para diseñar</title>
         <link>http://davidcapello.blogspot.com/2010/07/interfaces-graficas-interesantes-para.html</link>
         <description>Esta es una lista de interfaces gráficas interesantes para resolver:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Una interfaz gráfica que pueda ser usada inmediatamente por cualquiera que nunca haya visto una computadora.&lt;/li&gt;&lt;li&gt;Un lenguaje de scripting que me permita hacer &lt;i&gt;cualquier cosa&lt;/i&gt; en el sistema operativo, sin necesidad de escribir una línea de código. Por ejemplo, una interfaz para configurar una red de pipes y filtros, donde por las tuberías puede pasar cualquier tipo de dato (texto, datos binarios crudos, imágenes, audio, logs, planillas de excel, bases de dato, páginas web, mails, código fuente, etc.) y los filtros los pueden transformar en cualquier cosa.&lt;/li&gt;&lt;li&gt;Una interfaz que permita hacer control de versiones con Git con varios repositorios remotos de forma totalmente gráfica, sólo con el mouse. Comandos complejos como rebase podrían ser un simple drag and drop. Debería poder tener una visión de cada repositorio como una pequeña computadora a la que le puedo hacer pull y push (por branch). Etc.&lt;/li&gt;&lt;li&gt;Un editor de texto como Microsoft Word o OpenOffice.org Writer que produzca documentos de tan buena calidad como LaTeX.&lt;/li&gt;&lt;/ol&gt;Sólo ideas... (¿para proyectos open source? ¿para proyectos comerciales?)&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-6872667520697928652?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-6872667520697928652</guid>
         <pubDate>Mon, 26 Jul 2010 16:20:00 -0700</pubDate>
      </item>
      <item>
         <title>Montañas</title>
         <link>http://davidcapello.blogspot.com/2010/07/montanas.html</link>
         <description>Estaba escalando una montaña. Miro al cielo y un pájaro me garca. Pierdo el equilibro, la visibilidad, me resbalo.&lt;br /&gt;&lt;br /&gt;Hoy estoy tomando mates con Jim Morrison. Que buena yerba que consigue este tipo.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-8914455187945595896?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-8914455187945595896</guid>
         <pubDate>Mon, 26 Jul 2010 09:00:00 -0700</pubDate>
      </item>
      <item>
         <title>Alcance</title>
         <link>http://davidcapello.blogspot.com/2010/07/alcance.html</link>
         <description>Estaba comiendo en un bar. Levanto la vista y miro el televisor. Un tipo pidiendo limosna a un periodista. El periodista lo mira y le dice: &quot;Señor, yo estoy para mostrarle al mundo sus miserias&quot;. El tipo pega la vuelta y sigue comiendo basura. Yo sigo comiendo. Un pibe se acerca y me pide limosna. Lo miro, le doy una moneda, y pienso: &quot;Que poco puedo cambiar este mundo&quot;. Sigo comiendo.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-5871089010483199317?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-5871089010483199317</guid>
         <pubDate>Mon, 26 Jul 2010 04:09:00 -0700</pubDate>
      </item>
      <item>
         <title>Cuentos</title>
         <link>http://davidcapello.blogspot.com/2010/07/cuentos.html</link>
         <description>Un día un tipo se levantó de la cama y se puso a escribir un cuento. Para la noche ya lo había terminado. El cuento era tan bueno que no podía creerlo. Lo leyó una y otra vez, era increíble.&lt;br /&gt;&lt;br /&gt;Nunca más vieron al tipo.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-5453337935570027502?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-5453337935570027502</guid>
         <pubDate>Sun, 25 Jul 2010 14:42:00 -0700</pubDate>
      </item>
      <item>
         <title>Con el cerebro</title>
         <link>http://davidcapello.blogspot.com/2010/07/con-el-cerebro.html</link>
         <description>Llegará el día que programaremos con el cerebro. Los atajos de teclado no servirán de nada. Simplemente miro una ubicación, pienso en qué quiero escribir y... BAM! ahí van apareciendo las letras por arte de magia.&lt;br /&gt;&lt;br /&gt;Eso es un editor de texto.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-4047810170432875947?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-4047810170432875947</guid>
         <pubDate>Sun, 25 Jul 2010 04:26:00 -0700</pubDate>
      </item>
      <item>
         <title>MinGW Downloader</title>
         <link>http://davidcapello.blogspot.com/2010/06/mingw-downloader.html</link>
         <description>Do you want to install MinGW (gcc 4.5)? You can use &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://github.com/downloads/dacap/mingw-downloader/MinGW-Downloader-0.2.zip&quot;&gt;MinGW Downloader&lt;/a&gt;. Follow &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://github.com/dacap/mingw-downloader/raw/master/README.txt&quot;&gt;these intructions&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-4926538247158585651?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-4926538247158585651</guid>
         <pubDate>Sat, 12 Jun 2010 12:32:00 -0700</pubDate>
      </item>
      <item>
         <title>Descargar MinGW con gcc 4.5 automáticamente</title>
         <link>http://cmasomenos.blogspot.com/2010/06/descargar-mingw-con-gcc-45.html</link>
         <description>Este post se podría llamar:&lt;br /&gt;&lt;blockquote&gt;¿Cómo instalar MinGW?&lt;br /&gt;¿Cómo instalar y usar gcc 4.5 en Windows?&lt;br /&gt;¿Cómo compilar programas de C o C++ en Windows?&lt;br /&gt;O también, ¿puedo portar MinGW en un pendrive?&lt;br /&gt;&lt;/blockquote&gt;Cualquiera de los casos se responde con el siguiente archivo: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://github.com/downloads/dacap/mingw-downloader/MinGW-Downloader-0.2.zip&quot;&gt;MinGW-Downloader-0.2.zip&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Los pasos a seguir son los siguientes:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Cree una carpeta donde descomprimir MinGW-Downloader-0.2.zip (por ejemplo, C:&amp;#92;Compilers, o C:&amp;#92;GNU, lo importante es que la carpeta no tenga espacios!)&lt;br /&gt;&lt;li&gt;Descomprima MinGW-Downloader-0.2.zip en esa carpeta&lt;br /&gt;&lt;li&gt;Ejecute el archivo &quot;C:&amp;#92;Compilers&amp;#92;MinGW-Downloader&amp;#92;MinGW-4.5-Downloader.bat&quot;&lt;br /&gt;&lt;li&gt;Espere...&lt;br /&gt;&lt;li&gt;Una vez finalizado deberá ver algunos mensajes en la pantalla diciéndole si tuvo éxito (SUCCESS), inclusive el script intenta compilar un programa en C y otro en C++.&lt;br /&gt;&lt;li&gt;Listo, ya tiene MinGW con gcc 4.5 disponible en su máquina.&lt;br /&gt;&lt;/ol&gt;Puede usar el script &quot;Run-cmd-with-MinGW-4.5.bat&quot; para ejecutar la línea de comandos de Windows y tener el compilador disponible (gcc, g++, etc.) en la variable PATH. Lo importante es que el proceso de descarga no modifica ninguna variable de entorno suya (PATH), por lo tanto, podría borrar la carpeta &quot;C:&amp;#92;Compilers&quot; y empezar desde cero siempre que así lo desee.&lt;br /&gt;&lt;br /&gt;Puede mover la carpeta &quot;C:&amp;#92;Compilers&amp;#92;MinGW-Downloader&amp;#92;MinGW-4.5&quot; a &quot;C:&amp;#92;MinGW-4.5&quot; y borrar &quot;C:&amp;#92;Compilers&amp;#92;MinGW-Downloader&quot; completamente. Si quiere tener el compilador disponible desde cualquier aplicación (por ejemplo, desde un editor de texto o IDE), podría agregar la ruta &quot;C:&amp;#92;MinGW-4.5&amp;#92;bin&quot; a su PATH.&lt;br /&gt;&lt;br /&gt;Cabe destacar que la carpeta &quot;MinGW-4.5&quot; (&quot;C:&amp;#92;Compilers&amp;#92;MinGW-Downloader&amp;#92;MinGW-4.5&quot;) y el archivo &quot;Run-cmd-with-MinGW-4.5.bat&quot; los puede mover donde usted desee (por ejemplo, llevarlos en un pen drive), sólo tenga en cuenta que para hacer esto los dos tienen que estar en el mismo directorio (e.j. &quot;C:&amp;#92;MinGW-4.5&quot; y &quot;C:&amp;#92;Run-cmd-with-MinGW-4.5.bat&quot;).&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-5358250520945482732?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-5358250520945482732</guid>
         <pubDate>Sun, 06 Jun 2010 07:35:00 -0700</pubDate>
      </item>
      <item>
         <title>Shared Pointers de C++0x</title>
         <link>http://cmasomenos.blogspot.com/2010/05/shared-pointers-de-c0x.html</link>
         <description>En C usted puede hacer esto:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;&lt;br /&gt;struct Persona { };&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; Persona* a = malloc(sizeof(Persona));&lt;br /&gt; free(a);&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Un ejemplo equivalente en C++:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;class Persona { };&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; Persona* a = new Persona();&lt;br /&gt; delete a;&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Por cada &lt;b&gt;malloc&lt;/b&gt; existe un &lt;b&gt;free&lt;/b&gt; (al menos que use reallocs), y por cada &lt;b&gt;new&lt;/b&gt; existe un &lt;b&gt;delete&lt;/b&gt; (y por cada new[] un delete[]).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;¿Existe una forma por la cual C++ se &quot;entere&quot; que ya no quiero usar un puntero?&lt;/b&gt; La respuesta es: No, no existe. C++ no tiene un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)&quot;&gt;garbage collector&lt;/a&gt;. Pero existen &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://cmasomenos.blogspot.com/2009/11/punteros-por-ambito-scoped-pointers.html&quot;&gt;clases que pueden ayudarnos&lt;/a&gt;, como el viejo y tan poco querido &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://cmasomenos.blogspot.com/2008/06/excepciones-raii-y-autoptr.html&quot;&gt;auto_ptr&lt;/a&gt;, o los mejorados &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com/search?q=unique_ptr+Class&amp;btnI=1&quot;&gt;unique_ptr&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com/search?q=shared_ptr+Class&amp;btnI=1&quot;&gt;shared_ptr&lt;/a&gt; y &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com/search?q=weak_ptr+Class&amp;btnI=1&quot;&gt;weak_ptr&lt;/a&gt; del nuevo estándar de C++0x (o el &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/C%2B%2B_Technical_Report_1#Smart_pointers&quot;&gt;TR1&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Un &lt;em&gt;shared pointer&lt;/em&gt; es una clase que se encarga de guardar un puntero a un objeto (o tipo de dato), y cuenta la cantidad de referencias que se están haciendo a dicho objeto (es decir, la cantidad de shared pointers que apuntan al mismo objeto). El último shared pointer que se destruya (cuando las referencias llegan a cero), será el encargado de borrar el objeto apuntado (mediante un simple delete).&lt;br /&gt;&lt;br /&gt;Un ejemplo:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;memory&amp;gt; // Aquí debería estar shared_ptr&amp;lt;&amp;gt; (GCC 4.4)&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;class Persona {&lt;br /&gt; int n;&lt;br /&gt;&lt;br /&gt;public:&lt;br /&gt; Persona(int n) : n(n) {&lt;br /&gt; cout &amp;lt;&amp;lt; &quot;Nace la persona &quot; &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &quot;&amp;#92;n&quot;;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; ~Persona() { &lt;br /&gt; cout &amp;lt;&amp;lt; &quot;Muere la persona &quot; &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &quot;&amp;#92;n&quot;;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; static shared_ptr&amp;lt;Persona&amp;gt; Crear(int n) { &lt;br /&gt; return shared_ptr&amp;lt;Persona&amp;gt;(new Persona(n));&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; shared_ptr&amp;lt;Persona&amp;gt; a(new Persona(1));&lt;br /&gt; shared_ptr&amp;lt;Persona&amp;gt; b = Persona::Crear(2);&lt;br /&gt; shared_ptr&amp;lt;Persona&amp;gt; c;&lt;br /&gt;&lt;br /&gt; cout &amp;lt;&amp;lt; &quot;--- Aquí ambas personas existen ---&amp;#92;n&quot;;&lt;br /&gt;&lt;br /&gt; c = a; // Aquí c apunta a la persona 1&lt;br /&gt; b = c; // Ahora b apuntará a la persona 1 (la persona 2 muere porque&lt;br /&gt; // ya no existen referencias a ella)&lt;br /&gt;&lt;br /&gt; cout &amp;lt;&amp;lt; &quot;--- Aquí la persona 2 ya no existe ---&amp;#92;n&quot;;&lt;br /&gt; &lt;br /&gt; return 0;&lt;br /&gt;} // Aquí muere la persona 1 (a, b, c apuntaban a ella)&lt;br /&gt;&lt;/pre&gt;La salida del anterior programa es esta:&lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;Nace la persona 1&lt;br /&gt;Nace la persona 2&lt;br /&gt;--- Aquí ambas personas existen ---&lt;br /&gt;Muere la persona 2&lt;br /&gt;--- Aquí la persona 2 ya no existe ---&lt;br /&gt;Muere la persona 1&lt;br /&gt;&lt;/pre&gt;Como puede ver, en el anterior programa se llama sólo dos veces a &quot;new Persona&quot; y dos veces al destructor ~Persona. No debemos preocuparnos por usar &quot;delete&quot;, el shared_ptr&amp;lt;&amp;gt; hace todo por nosotros.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;¿Cómo hago para que la clase shared_ptr funcione en VS2008 SP1 Express?&lt;/b&gt; Debe definir _HAS_TR1 antes de incluir el archivo &amp;lt;memory&amp;gt;. Ejemplo:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#ifdef _MSC_VER // Si estamos usando el compilador de Microsoft&lt;br /&gt; #define _HAS_TR1 1 // Esto hará que se incluyan las clases del TR1 (std::tr1)&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;memory&amp;gt;&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;#ifdef _MSC_VER&lt;br /&gt; using namespace std::tr1; // para tener shared_ptr&amp;lt;&amp;gt; disponible&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;// Resto del ejemplo...&lt;br /&gt;&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-4303488601552155816?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-4303488601552155816</guid>
         <pubDate>Sat, 29 May 2010 08:59:00 -0700</pubDate>
      </item>
      <item>
         <title>C++0x Final Committee Draft (FCD)</title>
         <link>http://cmasomenos.blogspot.com/2010/03/c0x-final-committee-draft-fcd.html</link>
         <description>Ya está disponible el documento N3092, &lt;em&gt;Programming Languages — C++, Final Committee Draft&lt;/em&gt;. Este documento es el que más podría corresponder al nuevo estándar ISO de C++ (lo que viene de acá a uno o dos años pueden ser correcciones menores):&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3092.pdf&quot;&gt;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3092.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Más información &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://herbsutter.com/2010/03/13/trip-report-march-2010-iso-c-standards-meeting/&quot;&gt;acá&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-9151549130027944942?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-9151549130027944942</guid>
         <pubDate>Wed, 31 Mar 2010 02:07:00 -0700</pubDate>
      </item>
      <item>
         <title>ASE 0.8.0 Preview</title>
         <link>http://aseprite.blogspot.com/2010/03/ase-080-preview.html</link>
         <description>Preview of the upcoming ASE 0.8.0 (new tools):&lt;br /&gt;&lt;br /&gt;&lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://www.youtube.com/v/F76AMPxyhyQ&amp;hl=es&amp;fs=1&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt; New tools in the upcoming ASE 0.8.0: Elliptical marquee, lasso, polygonal lasso, magic wand, filled contour, and filled polygon. In this video you can see other things like: the pen preview, zoom when you are drawing a line, and the new GUI skin created by Ilija Melentijevic:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ilkke.blogspot.com/&quot;&gt;http://ilkke.blogspot.com/&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.pixeljoint.com/p/9270.htm&quot;&gt;http://www.pixeljoint.com/p/9270.htm&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-5266361223764207600?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-5266361223764207600</guid>
         <pubDate>Tue, 30 Mar 2010 18:32:00 -0700</pubDate>
      </item>
      <item>
         <title>Improving your applications by statistics</title>
         <link>http://davidcapello.blogspot.com/2010/03/improving-your-applications-by.html</link>
         <description>If you developed an application and published it in a website, you can use things like google-analytics data to adjust your application. E.g. If everybody is accessing your website with 32-bits, 24-bits and 16-bits screen resolutions, you can discard all considerations about 8-bits modes in your application.&lt;br /&gt;&lt;br /&gt;Things you should add to your application:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A way to get usage data from your users. E.g. where they do click, how they call commands (menus, keyboard, toolbars, ribbons, etc.). In this way you could focus improvement in the more common methods to run commands.&lt;/li&gt;&lt;li&gt;A way to count how many times a command was used. Maybe there are commands that are rarely used, these commands could be more deeper in menus hierarchies and without keyboard shortcut.&lt;/li&gt;&lt;li&gt;A way to known systems where your application is running. E.g. operating system, version, screen resolution, etc. Improve usability in the most used platform.&lt;/li&gt;&lt;li&gt;A way to known how many computers are running a specific version of your application. If a version is not used anymore, you can stop supporting it (E.g. Adding patches for a version that nobody uses).&lt;/li&gt;&lt;/ul&gt;All this must be done carefully, with proper check-boxes like &quot;Do you want to send anonymous data about your usage to improve customer experience?&quot; in installers, splash screens, etc.&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.eclipse.org/epp/usagedata/&quot;&gt;There are some frameworks&lt;/a&gt; to do this kind of work. Anyway you basically need:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;An HTTP server to accept packages from users (e.g. through POST requests). Each request should be processed by a script (in PHP, ASP, etc.) which should convert the received package into database model.&lt;/li&gt;&lt;li&gt;A way to differentiate users (you could SHA1 some string like &quot;local user name + pc host name + app name version&quot;). Here I don't know if the IP could be a good way idea (NAT problems, etc.).&lt;/li&gt;&lt;li&gt;A way to make HTTP requests from your application (firewall + proxy problems) of all collected usage data of the user (identified by the SHA1).&lt;/li&gt;&lt;li&gt;A mini-program to process all the database and print some useful reports.&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-5688955183809224891?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-5688955183809224891</guid>
         <pubDate>Wed, 03 Mar 2010 14:45:00 -0800</pubDate>
      </item>
      <item>
         <title>Emacs tips for Windows: How to locate the current buffer in Windows Explorer?</title>
         <link>http://davidcapello.blogspot.com/2010/03/emacs-tips-for-windows-how-to-locate.html</link>
         <description>You can use the following function to open the Windows Explorer in the directory of the current buffer:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;(defun locate-current-file-in-explorer ()&lt;br /&gt; (interactive)&lt;br /&gt; (cond&lt;br /&gt; ;; In buffers with file name&lt;br /&gt; ((buffer-file-name)&lt;br /&gt; (shell-command (concat &quot;start explorer /e,/select,&amp;#92;&quot;&quot; (replace-regexp-in-string &quot;/&quot; &quot;&amp;#92;&amp;#92;&amp;#92;&amp;#92;&quot; (buffer-file-name)) &quot;&amp;#92;&quot;&quot;)))&lt;br /&gt; ;; In dired mode&lt;br /&gt; ((eq major-mode 'dired-mode)&lt;br /&gt; (shell-command (concat &quot;start explorer /e,&amp;#92;&quot;&quot; (replace-regexp-in-string &quot;/&quot; &quot;&amp;#92;&amp;#92;&amp;#92;&amp;#92;&quot; (dired-current-directory)) &quot;&amp;#92;&quot;&quot;)))&lt;br /&gt; ;; In eshell mode&lt;br /&gt; ((eq major-mode 'eshell-mode)&lt;br /&gt; (shell-command (concat &quot;start explorer /e,&amp;#92;&quot;&quot; (replace-regexp-in-string &quot;/&quot; &quot;&amp;#92;&amp;#92;&amp;#92;&amp;#92;&quot; (eshell/pwd)) &quot;&amp;#92;&quot;&quot;)))&lt;br /&gt; ;; Use default-directory as last resource&lt;br /&gt; (t&lt;br /&gt; (shell-command (concat &quot;start explorer /e,&amp;#92;&quot;&quot; (replace-regexp-in-string &quot;/&quot; &quot;&amp;#92;&amp;#92;&amp;#92;&amp;#92;&quot; default-directory) &quot;&amp;#92;&quot;&quot;)))))&lt;br /&gt;&lt;/pre&gt;How it works?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If you are visiting a buffer associated to a file (with buffer-file-name), the Windows Explorer is opened to focus the file in its directory.&lt;/li&gt;&lt;li&gt;If you are in dired mode (browsing a directory inside Emacs with dired-mode), it will open that directory in Windows Explorer.&lt;/li&gt;&lt;li&gt;If you are in eshell-mode, the current working directory will be opened in Windows Explorer.&lt;/li&gt;&lt;li&gt;As last chance it will open the Windows Explorer in the default directory (where you start emacs). E.g. This can happen if you use this function in *scratch* buffer (which is a buffer without an associated file).&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-6017722888505044435?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-6017722888505044435</guid>
         <pubDate>Tue, 02 Mar 2010 13:17:00 -0800</pubDate>
      </item>
      <item>
         <title>Emacs tips for Windows: How to open the current buffer with associated application?</title>
         <link>http://davidcapello.blogspot.com/2010/03/emacs-tips-for-windows-how-to-open.html</link>
         <description>The following function tries to run the application associated with the current buffer file type (e.g. if you use this function in an .html file, the file will be opened with your default web browser):&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;(defun open-current-file-with-associated-app ()&lt;br /&gt; (interactive)&lt;br /&gt; (shell-command (concat &quot;cmd /c &amp;#92;&quot;start &quot; (buffer-file-name) &quot;&amp;#92;&quot;&quot;)))&lt;br /&gt;&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-8289950529485041277?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-8289950529485041277</guid>
         <pubDate>Tue, 02 Mar 2010 13:15:00 -0800</pubDate>
      </item>
      <item>
         <title>ASE migrated to Git</title>
         <link>http://aseprite.blogspot.com/2010/02/ase-migrated-to-git.html</link>
         <description>ASE repository was migrated to Git. You can clone the repository with the following command:&lt;br /&gt;&lt;pre&gt; git clone git://ase.git.sourceforge.net/gitroot/ase/ase&lt;br /&gt;&lt;/pre&gt;Get a Git client for Windows &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/p/msysgit/&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can browse ASE patches &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ase.git.sourceforge.net/git/gitweb.cgi?p=ase/ase;a=summary&quot;&gt;here&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-5481839952971888638?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-5481839952971888638</guid>
         <pubDate>Sun, 28 Feb 2010 05:20:00 -0800</pubDate>
      </item>
      <item>
         <title>Who Made Who</title>
         <link>http://davidcapello.blogspot.com/2010/01/who-made-who.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=a3HemKGDavw&quot;&gt;Led Zeppelin&lt;/a&gt; vs &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=6GNd6vcWm4Q#t=38s&quot;&gt;Riff&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=Vd38yrWx2o0&quot;&gt;The Beatles&lt;/a&gt; vs &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=pUzTar7MRCU#t=10s&quot;&gt;Vox Dei&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://video.google.com/videoplay?docid=-4990093840803503932#3m45s&quot;&gt;Queen&lt;/a&gt; vs &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=S5j-S6Eq81g#t=2m20s&quot;&gt;The Beatles&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=1FIOjLwwj-U#t=1m28s&quot;&gt;Styx&lt;/a&gt; vs &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=aDvUBA7kCYs#t=1m35s&quot;&gt;Queen&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=nLKxvjbWULQ&quot;&gt;Stevie Ray Vaughan&lt;/a&gt; vs &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com/search?q=&quot;el+gallo+negro&quot;+jaf&quot;&gt;JAF&lt;/a&gt; (lo siento, no encontré un audio directo a El Gallo Negro de JAF)&lt;br /&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=cNhnThb8gEw&quot;&gt;J. Geils Band&lt;/a&gt; vs &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.youtube.com/watch?v=DyuHTfKY7L4&quot;&gt;Sumo&lt;/a&gt; (...bueno, ya menti demasiado)&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-4539345055114405519?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-4539345055114405519</guid>
         <pubDate>Thu, 28 Jan 2010 16:08:00 -0800</pubDate>
      </item>
      <item>
         <title>STL string, parseando un número de versión</title>
         <link>http://cmasomenos.blogspot.com/2010/01/stl-string-parseando-un-numero-de.html</link>
         <description>En esta ocasión vamos a ver cómo usar la clase &lt;em&gt;std::string&lt;/em&gt; para convertir una cadena de caracteres (como &quot;1.2.3&quot;) en una clase &quot;Version&quot; que tenga una interfaz simple de utilizar (por ejemplo, que permita comparar versiones).&lt;br /&gt;&lt;br /&gt;Los pasos son simples:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;tenemos como entrada una cadena de caracteres,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;dividimos la cadena según el caracter '.' (punto),&lt;br /&gt;&lt;/li&gt;&lt;li&gt;convertimos cada parte a entero,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;guardamos cada número entero de forma ordenada en un vector.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;El punto 2 es en el cual nos vamos a enfocar más. &lt;em&gt;El código mostrado aquí es a modo de ejemplo, y está lejos de ser el más óptimo.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Antes de comenzar ¿Podemos usar &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/clibrary/cstring/strcmp/&quot;&gt;strcmp&lt;/a&gt; para comparar dos versiones?&lt;/b&gt; No, no podemos. Ejemplo: strcmp(&quot;1.9&quot;, &quot;1.10&quot;) &amp;gt; 0, cuando en realidad la versión 1.9 es menor a 1.10.&lt;br /&gt;&lt;br /&gt;Imaginemos que tenemos una cadena: &lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;std::string ver = &quot;1.10.2.3&quot;;&lt;br /&gt;&lt;/pre&gt;La clase &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/string/string/&quot;&gt;std::string&lt;/a&gt; tiene la función miembro &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/string/string/find/&quot;&gt;find&lt;/a&gt;, la cual podemos usar para buscar casi cualquier cosa dentro de la cadena. ¿Qué debemos buscar? Los puntos, sabiendo donde está cada punto, podemos ir recortando la cadena en sus distintas partes (&quot;1&quot;, &quot;10&quot;, &quot;2&quot;, y &quot;3&quot;). Buscamos la ubicación del primer punto: &lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;size_t i = ver.find('.');&lt;br /&gt;&lt;br /&gt;if (i != std::string::npos)&lt;br /&gt; std::printf(&quot;El punto fue encontrado en la posición %d&amp;#92;n&quot;, i);&lt;br /&gt;else&lt;br /&gt; std::printf(&quot;No hay punto en la cadena&amp;#92;n&quot;);&lt;br /&gt;&lt;/pre&gt;Ejecutando el código anterior, deberíamos obtener el mensaje: &lt;br /&gt;&lt;pre&gt;El punto fue encontrado en la posición 1&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;¿Qué es &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/clibrary/cstring/size_t/&quot;&gt;size_t&lt;/a&gt;?&lt;/b&gt; Es como el tipo &quot;unsigned int&quot;, el tipo de dato retornado por el operador &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cppreference.com/wiki/keywords/sizeof&quot;&gt;sizeof()&lt;/a&gt; y utilizado como índice en las funciones de std::string.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;¿Qué es &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/string/string/npos/&quot;&gt;std::string::npos&lt;/a&gt;?&lt;/b&gt; Es el máximo valor posible de un &lt;em&gt;size_t&lt;/em&gt; y se utiliza para indicar (en este caso) que la función &lt;em&gt;find&lt;/em&gt; falló (no encontró el punto).&lt;br /&gt;&lt;br /&gt;Una vez que tenemos la posición del punto, podemos obtener la porción de texto que contiene la primer cifra, para eso usamos la función miembro &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/string/string/substr/&quot;&gt;substr&lt;/a&gt;: &lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;std::string primer_cifra = ver.substr(0, i);&lt;br /&gt;&lt;/pre&gt;Esto significa: &lt;em&gt;che vos, función substr, devolveme el pedazo de cadena de caracteres que va desde el índice 0, y tiene una longitud de i-caracteres.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;El proceso puede ser repetido tantas veces como queramos para seguir obteniendo cifras. Por ejemplo, para la siguiente cifra debemos buscar (find) el siguiente punto, pero comenzando desde el que encontramos hace un rato: &lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;i++; // ir a la posición siguiente del punto '.'&lt;br /&gt;size_t j = ver.find('.', i);&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;¿Qué es (o hace) el segundo argumento de find?&lt;/b&gt; Le indica a la función desde donde debe comenzar a buscar. La primera vez que usamos find este argumento no se especificó, porque por omisión toma el valor 0, es decir, buscar desde el inicio de la cadena.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;¿Por qué i++?&lt;/b&gt; Porque si comenzáramos a buscar un punto desde &lt;em&gt;i&lt;/em&gt;, nos devolvería la misma posición &lt;em&gt;i&lt;/em&gt; (porque justamente, en &lt;em&gt;i&lt;/em&gt;, está el primer punto que encontramos). Entonces debemos avanzar una posición.&lt;br /&gt;&lt;br /&gt;Ahora, debemos recortar la segunda cifra: &lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;std::string segunda_cifra = ver.substr(i, j-i);&lt;br /&gt;&lt;/pre&gt;La segunda cifra, comienza desde &lt;em&gt;i&lt;/em&gt; y tiene una longitud igual a &lt;em&gt;j-i&lt;/em&gt;. Para comprender esto, vea la siguiente figura:&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear:both;text-align:center;&quot;&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://3.bp.blogspot.com/_LUOxBrR4np4/S2DDl0pVkfI/AAAAAAAAAds/pDJ8xqGYqEE/s1600-h/std_string_indices.png&quot; style=&quot;margin-left:1em;margin-right:1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;155&quot; src=&quot;http://3.bp.blogspot.com/_LUOxBrR4np4/S2DDl0pVkfI/AAAAAAAAAds/pDJ8xqGYqEE/s400/std_string_indices.png&quot; width=&quot;400&quot;/&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;De esta forma, &lt;em&gt;ver.substr(i, j-i)&lt;/em&gt; nos devuelve la cadena &quot;10&quot;. La versión completa del algoritmo puede quedar algo así:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;vector&amp;gt; // Por std::vector&lt;br /&gt;#include &amp;lt;string&amp;gt; // Por std::string&lt;br /&gt;#include &amp;lt;cstdlib&amp;gt; // Por std::strtol&lt;br /&gt;#include &amp;lt;cstdio&amp;gt; // Por std::printf&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; std::string ver = &quot;1.10.2.3&quot;;&lt;br /&gt;&lt;br /&gt; // Vector con cada cifra.&lt;br /&gt; // Luego del procesamiento esto debería ser = { 1, 10, 2, 3 }&lt;br /&gt; std::vector&amp;lt;int&amp;gt; cifras;&lt;br /&gt;&lt;br /&gt; size_t i = 0; // Comenzamos desde i=0&lt;br /&gt; size_t j = 0;&lt;br /&gt;&lt;br /&gt; // Repetir hasta no llegar al final de la cadena&lt;br /&gt; while (j != std::string::npos) {&lt;br /&gt; // Buscar próximo punto&lt;br /&gt; j = ver.find('.', i);&lt;br /&gt;&lt;br /&gt; std::string cifra;&lt;br /&gt;&lt;br /&gt; // Si se encontró un punto&lt;br /&gt; if (j != std::string::npos) {&lt;br /&gt; // Recortamos desde i hasta j&lt;br /&gt; cifra = ver.substr(i, j-i);&lt;br /&gt;&lt;br /&gt; // El nuevo comienzo para buscar puntos será &quot;j+1&quot;&lt;br /&gt; i = j+1;&lt;br /&gt; }&lt;br /&gt; // Si no se encontró un punto&lt;br /&gt; else {&lt;br /&gt; // Recortamos desde &quot;i&quot; hasta el final de la cadena&lt;br /&gt; cifra = ver.substr(i);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // Obtener el valor entero de la cifra&lt;br /&gt; int cifra_int = std::strtol(cifra.c_str(), NULL, 10);&lt;br /&gt;&lt;br /&gt; // Agregar la cifra al vector&lt;br /&gt; cifras.push_back(cifra_int);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; for (size_t i=0; i&amp;lt;cifras.size(); ++i)&lt;br /&gt; printf(&quot;cifras[%d] = %d&amp;#92;n&quot;, i, cifras[i]);&lt;br /&gt;&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;La salida del anterior programa es:&lt;br /&gt;&lt;pre&gt;cifras[0] = 1&lt;br /&gt;cifras[1] = 10&lt;br /&gt;cifras[2] = 2&lt;br /&gt;cifras[3] = 3&lt;br /&gt;&lt;/pre&gt;Con este código, podríamos implementar una clase &quot;Version&quot; con la siguiente interfaz:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;class Version&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; Version(const char*);&lt;br /&gt; Version(const std::string&amp;amp;);&lt;br /&gt;&lt;br /&gt; bool operator==(const Version&amp;amp; u) const;&lt;br /&gt; bool operator&amp;lt;(const Version&amp;amp; u) const;&lt;br /&gt; // ...&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;En un próximo post voy a colocar una posible implementación de la clase &quot;Version&quot;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-1740419321130176820?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-1740419321130176820</guid>
         <pubDate>Wed, 27 Jan 2010 12:14:00 -0800</pubDate>
         <media:thumbnail width="72" url="http://3.bp.blogspot.com/_LUOxBrR4np4/S2DDl0pVkfI/AAAAAAAAAds/pDJ8xqGYqEE/s72-c/std_string_indices.png" height="72" xmlns:media="http://search.yahoo.com/mrss/"/>
      </item>
      <item>
         <title>Uploading Progress</title>
         <link>http://davidcapello.blogspot.com/2010/01/uploading-progress.html</link>
         <description>At the moment, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com/chrome&quot;&gt;Google Chrome&lt;/a&gt; (4.0.302.3) is the only browser which shows the uploading progress when you send a file through a &amp;lt;form&amp;gt;. Really useful when you upload big files in a Google Code project.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-5828647273303794455?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-5828647273303794455</guid>
         <pubDate>Tue, 26 Jan 2010 15:22:00 -0800</pubDate>
      </item>
      <item>
         <title>Split reStructuredText HTML output file</title>
         <link>http://davidcapello.blogspot.com/2009/12/split-restructuredtext-html-output-file.html</link>
         <description>Maybe I am so stupid that I do not found the way (program parameters?, extra utility?) to split a &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://docutils.sourceforge.net/rst.html&quot;&gt;reStructuredText&lt;/a&gt;'s HTML output in various HTMLs files.&lt;br /&gt;&lt;br /&gt;In these days I'm preparing some documentation for &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.aseprite.org/&quot;&gt;ASE&lt;/a&gt;, and I'm using reStructuredText (rst), but I wanted to split the output in different HTML files (one per section). Anyway I don't find a way to do this.&lt;br /&gt;&lt;br /&gt;This can be useful for other people so I'm publishing &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ase.svn.sourceforge.net/viewvc/ase/trunk/docs/manual/split.py?revision=309&amp;view=markup&quot;&gt;this Python 2.6 script&lt;/a&gt; which splits the rst2html.py HTML output file in various HTML files.&lt;br /&gt;&lt;br /&gt;You should/could tune up the script because it:&lt;br /&gt;1) reads the rst output from a file called &quot;manual.html&quot;,&lt;br /&gt;2) splits the table of content creating &quot;index.html&quot; (so your file should contain a table of content),&lt;br /&gt;3) converts each section &amp;lt;div class=&quot;section&quot; id=&quot;&lt;em&gt;section-name&lt;/em&gt;&quot;&amp;gt; to a &lt;em&gt;section-name&lt;/em&gt;.html file,&lt;br /&gt;4) every &amp;lt;a href=&quot;...&quot;&amp;gt; in created HTML files will be point to the new location.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-1085083355473415712?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-1085083355473415712</guid>
         <pubDate>Wed, 09 Dec 2009 12:17:00 -0800</pubDate>
      </item>
      <item>
         <title>Punteros por ámbito (scoped pointers)</title>
         <link>http://cmasomenos.blogspot.com/2009/11/punteros-por-ambito-scoped-pointers.html</link>
         <description>C++ no tiene un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/Recolector_de_basura&quot;&gt;recolector de basura&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.research.att.com/~bs/C++0xFAQ.html#gc-abi&quot;&gt;aunque C++0x le va tomando el gustito&lt;/a&gt;, tenemos algunas opciones para liberarnos de liberar memoria, valga la redundancia.&lt;br /&gt;&lt;br /&gt;Imaginemos un código como el siguiente:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;class A {&lt;br /&gt;public:&lt;br /&gt; A() { printf(&quot;A&amp;#92;n&quot;); }&lt;br /&gt; ~A() { printf(&quot;~A&amp;#92;n&quot;); }&lt;br /&gt; void hola() { printf(&quot;hola&amp;#92;n&quot;); }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; A* a = new A;&lt;br /&gt; a-&amp;gt;hola();&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;El anterior programa, por más &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Minimalism&quot;&gt;minimalista&lt;/a&gt; que parezca, tiene un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Memory_leak&quot;&gt;memory leak&lt;/a&gt;. Aunque los &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Resource_(computer_science)&quot;&gt;recursos&lt;/a&gt; suelen ser liberados por el mismo sistema operativo al finalizar el programa, si el proceso se ejecuta por mucho tiempo (e.j. un servicio que se ejecuta por días, semanas o meses dentro de un servidor), los recursos se van agotando poco a poco hasta que la computadora queda hecha una &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/Pasa&quot;&gt;pasa&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para arreglar el leak, deberíamos escribir:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;int main()&lt;br /&gt;{&lt;br /&gt; A* a = new A;&lt;br /&gt; a-&amp;gt;hola();&lt;br /&gt; &lt;b&gt;delete a;&lt;/b&gt;&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;¿Cómo hacemos para liberar memoria sin llamar &lt;i&gt;delete&lt;/i&gt; nosotros mismos?&lt;/b&gt; Podemos crear una clase utilitaria que haga el trabajo por nosotros en su destructor. Por ejemplo, en el siguiente código veremos que el delete es llamado en el destructor de PunteroA:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;class PunteroA {&lt;br /&gt; A* ptr;&lt;br /&gt;public:&lt;br /&gt; PunteroA(A* p) { ptr = p; }&lt;br /&gt; &lt;b&gt;~PunteroA() { delete ptr; }&lt;/b&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; PunteroA a(new A);&lt;br /&gt; a-&amp;gt;hola(); // error, &quot;a&quot; no es un puntero ni sobrecarga operator-&amp;gt;&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;El anterior programa nos dará un error de compilación ya que el tipo PunteroA no soporta el operador flecha. Debemos agregarlo en la definición de la clase PunteroA:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;class PunteroA {&lt;br /&gt; A* ptr;&lt;br /&gt;public:&lt;br /&gt; PunteroA(A* p) { ptr = p; }&lt;br /&gt; ~PunteroA() { delete ptr; }&lt;br /&gt; &lt;b&gt;A* operator-&amp;gt;() { return ptr; }&lt;/b&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; PunteroA a(new A);&lt;br /&gt; a-&amp;gt;hola(); // ahora sí, PunteroA::operator-&amp;gt;() nos devuelve&lt;br /&gt; // el verdadero puntero A* y A::hola() finalmente&lt;br /&gt; // es llamado&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;¿Cómo obtengo el A* desde un PunteroA?&lt;/b&gt; Debemos definir el operador de conversión hacia A*:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;class PunteroA {&lt;br /&gt; A* ptr;&lt;br /&gt;public:&lt;br /&gt; PunteroA(A* p) { ptr = p; }&lt;br /&gt; ~PunteroA() { delete ptr; }&lt;br /&gt; A* operator-&amp;gt;() { return ptr; }&lt;br /&gt; &lt;b&gt;operator A*() { return ptr; }&lt;/b&gt;&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;Así podemos usar un PunteroA en funciones que reciban un A*. Ejemplo:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;void func(A* a) { ... }&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; PunteroA a(new A);&lt;br /&gt; func(a);&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;Generalizando:&lt;/b&gt; Podemos generalizar nuestro PunteroA para cualquier tipo de dato:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;template&amp;lt;class T&amp;gt;&lt;br /&gt;class ScopedPointer {&lt;br /&gt; T* ptr;&lt;br /&gt;public:&lt;br /&gt; ScopedPointer(T* p) { ptr = p; }&lt;br /&gt; ~ScopedPointer() { delete ptr; }&lt;br /&gt; &lt;br /&gt; operator T*() { return ptr; }&lt;br /&gt; T* operator-&amp;gt;() { return ptr; }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;Así podemos usar el mismo ScopedPointer para liberar instancias de cualquier clase:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;int main()&lt;br /&gt;{&lt;br /&gt; ScopedPointer&amp;lt;A&amp;gt; a(new A);&lt;br /&gt; ScopedPointer&amp;lt;B&amp;gt; b(new B);&lt;br /&gt; a-&amp;gt;hola();&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;¿Y si quiero liberar otro tipo de recurso?&lt;/b&gt; Si el recurso no es memoria, y es liberado con otra función en vez de delete, podemos generalizar nuestro ScopedPointer con un nuevo parámetro de plantilla llamado &lt;i&gt;Destroyer&lt;/i&gt;:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;struct DefaultDestroyer {&lt;br /&gt; template&amp;lt;class T&amp;gt;&lt;br /&gt; static void &lt;b&gt;free&lt;/b&gt;(T* ptr) { delete ptr; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;template&amp;lt;class T, class &lt;b&gt;Destroyer&lt;/b&gt; = DefaultDestroyer&amp;gt;&lt;br /&gt;class ScopedPointer {&lt;br /&gt; T* ptr;&lt;br /&gt;public:&lt;br /&gt; ScopedPointer(T* p) { ptr = p; }&lt;br /&gt; ~ScopedPointer() { &lt;b&gt;Destroyer::free(ptr);&lt;/b&gt; }&lt;br /&gt; &lt;br /&gt; operator T*() { return ptr; }&lt;br /&gt; T* operator-&amp;gt;() { return ptr; }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;En este caso, el destructor ~ScopedPointer llama a la función estática Destroyer::free. Esta función básicamente puede hacer lo que nosotros queramos. Podría ser útil para liberar ficheros o cualquier otro tipo de recurso:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;struct FileDestroyer {&lt;br /&gt; static void free(FILE* ptr) { fclose(ptr); }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; ScopedPointer&amp;lt;FILE, FileDestroyer&amp;gt; file(fopen(&quot;hola.txt&quot;, &quot;rt&quot;));&lt;br /&gt; char buf[256];&lt;br /&gt; fread(buf, 1, 256, file);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;¿No existen punteros de este tipo ya implementados?&lt;/b&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.boost.org/&quot;&gt;Boost&lt;/a&gt; tiene su propio &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.boost.org/doc/libs/1_40_0/libs/smart_ptr/scoped_ptr.htm&quot;&gt;scoped_ptr&lt;/a&gt;. También existen punteros más avanzados que cuentan referencias, como los &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/C%2B%2B0x#General-purpose_smart_pointers&quot;&gt;smart pointers&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-8183254772973387343?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-8183254772973387343</guid>
         <pubDate>Thu, 05 Nov 2009 16:50:00 -0800</pubDate>
      </item>
      <item>
         <title>Interfaces vs. Conceptos</title>
         <link>http://cmasomenos.blogspot.com/2009/10/interfaces-vs-conceptos.html</link>
         <description>¿Qué son los conceptos? Vamos a ver con un simple ejemplo, cómo podemos hacer una equivalencia entre las conocidas &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Interface_(computer_science)&quot;&gt;interfaces&lt;/a&gt; y los &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Concept_(generic_programming)&quot;&gt;conceptos&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Imaginen esta &quot;interfaz&quot; (clase abstracta):&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;class IPortero {&lt;br /&gt;public:&lt;br /&gt; virtual IPortero() { }&lt;br /&gt; virtual void ir_a_piso(int piso) = 0;&lt;br /&gt; virtual int piso_destino() = 0;&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;Tenemos otra clase Ascensor que podemos &quot;personalizar&quot; con nuestro propio portero, así nuestra implementación de portero puede hacer &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/Ascensor#Algoritmos_de_Maniobras&quot;&gt;lo que se le de la gana&lt;/a&gt;:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;class Ascensor {&lt;br /&gt; IPortero* m_portero;&lt;br /&gt;public:&lt;br /&gt; Ascensor(IPortero* portero) {&lt;br /&gt; m_portero = portero;&lt;br /&gt; }&lt;br /&gt; void apretaron_boton_en_piso(int piso) {&lt;br /&gt; m_portero-&amp;gt;ir_a_piso(piso);&lt;br /&gt; mover_ascensor(m_portero-&amp;gt;piso_destino());&lt;br /&gt; }&lt;br /&gt; void mover_ascensor(int piso) { ... }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;Con programación genérica, podemos reformular la interfaz convirtiéndola en un &quot;concepto&quot; y la clase Ascensor en una clase plantilla:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;template&amp;lt;class TipoPortero&amp;gt;&lt;br /&gt;class Ascensor {&lt;br /&gt; TipoPortero m_portero;&lt;br /&gt;public:&lt;br /&gt; Ascensor() { }&lt;br /&gt; void apretaron_boton_en_piso(int piso) {&lt;br /&gt; m_portero.ir_a_piso(piso);&lt;br /&gt; mover_ascensor(m_portero.piso_destino());&lt;br /&gt; }&lt;br /&gt; void mover_ascensor(int piso) { ... }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;La pregunta es, &lt;em&gt;¿qué demonios es TipoPortero?&lt;/em&gt;. La respuesta es sencilla: TipoPortero puede ser cualquier tipo de dato que cumpla los siguientes requisitos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Tenga un constructor por omisión (que se pueda construir un nuevo TipoPortero sin argumentos, o sea, &lt;em&gt;TipoPortero()&lt;/em&gt;).&lt;br /&gt;&lt;li&gt;Tenga una función miembro &lt;em&gt;TipoPortero::ir_a_piso(int)&lt;/em&gt;, la cual recibe un &quot;int&quot; (o cualquier tipo de dato que se pueda construir desde un &quot;int&quot; implícitamente).&lt;br /&gt;&lt;li&gt;Y otra función miembro &lt;em&gt;TipoPortero::piso_destino()&lt;/em&gt; que devuelve un entero.&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;&lt;b&gt;¿Cómo especificamos la &quot;interfaz&quot; o los &quot;requerimientos&quot; de un concepto?&lt;/b&gt; Sencillamente no se puede, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://cmasomenos.blogspot.com/2009/07/c0x-no-va-tener-conceptos.html&quot;&gt;C++0x iba a soportar esto&lt;/a&gt;, pero ya no. Hoy en día la mejor respuesta es usar algunos comentarios en la clase Ascensor que especifiquen qué espera en sus parámetros de template. En este aspecto se podría decir que IPortero es mejor porque especifica explícitamente lo que el portero tiene que hacer (funciones a implementar, etc.).&lt;p&gt;&lt;b&gt;¿Qué ventaja tiene el concepto con respecto a las interfaces?&lt;/b&gt; La clase genérica Ascensor ahora tiene el mismo portero adentro suyo (no un puntero a la interfaz). Las llamadas a las funciones miembro &lt;em&gt;ir_a_piso&lt;/em&gt; y &lt;em&gt;piso_destino&lt;/em&gt; son llamadas directas (no tienen el &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Virtual_method_table#Efficiency&quot;&gt;overhead de una llamada a una función virtual&lt;/a&gt;).&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-3720137353173753110?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-3720137353173753110</guid>
         <pubDate>Sun, 18 Oct 2009 05:21:00 -0700</pubDate>
      </item>
      <item>
         <title>Sobras</title>
         <link>http://davidcapello.blogspot.com/2009/10/sobras.html</link>
         <description>Más música &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.davidcapello.com.ar/musics/&quot;&gt;en la página&lt;/a&gt;. Se podría decir que es un nuevo &quot;álbum&quot;, pero sólo son tres temas locos (uno de los cuales dura menos que un minuto).&lt;br /&gt;&lt;br /&gt;El álbum en Jamendo:&lt;br /&gt;&lt;br /&gt;&lt;div style=&quot;text-align:center;margin-bottom:2px;&quot;&gt;&lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://widgets.jamendo.com/es/album/?album_id=53917&amp;playertype=2008&amp;refuid=224523&quot; width=&quot;200&quot; height=&quot;300&quot; align=&quot;middle&quot; type=&quot;application/x-shockwave-flash&quot; pluginspage=&quot;http://www.macromedia.com/go/getflashplayer&quot;&gt;&amp;nbsp;&lt;/iframe&gt;&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-1291087453104363511?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-1291087453104363511</guid>
         <pubDate>Sun, 18 Oct 2009 04:26:00 -0700</pubDate>
      </item>
      <item>
         <title>Clases que &quot;desaparecen&quot; luego de compilar</title>
         <link>http://cmasomenos.blogspot.com/2009/10/clases-que-desaparecen-luego-de.html</link>
         <description>La magia de C++ es que, una vez compilado el código, algunas clases pueden desaparecer por completo (principalmente las que se usan en &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Call_stack&quot;&gt;stack&lt;/a&gt;). O sea, aunque las clases abstraen al programador de los detalles de implementación, al final, el código termina siendo tan óptimo como si la clase no fuera utilizada en un principio.&lt;br /&gt;&lt;br /&gt;Un ejemplo. Teniendo la siguiente clase Acumulador:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;&lt;br /&gt;class Acumulador {&lt;br /&gt; int v;&lt;br /&gt;public:&lt;br /&gt; Acumulador() { v = 0; }&lt;br /&gt; ~Acumulador() { std::printf(&quot;%d&amp;#92;n&quot;, v); }&lt;br /&gt; void acumular(int x) { v += x; }&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;Un código como el siguiente:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;{&lt;br /&gt; Acumulador acum;&lt;br /&gt; acum.acumular(2);&lt;br /&gt; acum.acumular(4);&lt;br /&gt; acum.acumular(10);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Al compilarlo (optimizándolo), el código equivale a exactamente esto:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;{&lt;br /&gt; int v = 0;&lt;br /&gt; v += 2;&lt;br /&gt; v += 4;&lt;br /&gt; v += 10;&lt;br /&gt; std::printf(&quot;%d&amp;#92;n&quot;, v);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;La clase Acumulador ya no existe. Obtenemos el código más óptimo posible: sin llamadas a la función &quot;acumular&quot;, ni ningún byte extra de memoria (Acumulador ocupa lo mismo de memoria que ocupa un &quot;int&quot;).&lt;br /&gt;&lt;br /&gt;Este ejemplo no ayuda a ver grandes ventajas, pero si el constructor y el destructor hacen tareas complicadas, y las funciones miembros también, el resultado puede llevarnos a dos puntos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Nos abstrae de la complejidad de la implementación (e.j. &lt;em&gt;para qué quiero saber cómo se acumula si sólo quiero acumular&lt;/em&gt;)&lt;br /&gt;&lt;li&gt;Obtenemos código tan óptimo como si no hubiéramos usado la abstracción (e.j. &lt;em&gt;las operaciones se acercan al hardware tanto como sea posible&lt;/em&gt;).&lt;br /&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-4223411900424123051?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-4223411900424123051</guid>
         <pubDate>Sat, 17 Oct 2009 14:50:00 -0700</pubDate>
      </item>
      <item>
         <title>SourceForge habla de Allegro Sprite Editor</title>
         <link>http://davidcapello.blogspot.com/2009/10/sourceforge-habla-de-allegro-sprite.html</link>
         <description>Hoy salió &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://sourceforge.net/community/allegro-con-spirito-a-graphics-editor-for-sprites/&quot;&gt;un artículo&lt;/a&gt; sobre &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.aseprite.org/&quot;&gt;Allegro Sprite Editor&lt;/a&gt; en la SourceForge Community.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-3253536967632669966?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-3253536967632669966</guid>
         <pubDate>Tue, 13 Oct 2009 13:32:00 -0700</pubDate>
      </item>
      <item>
         <title>Las viejas home pages</title>
         <link>http://davidcapello.blogspot.com/2009/10/las-viejas-home-pages.html</link>
         <description>(Una nota que nadie nunca leerá)&lt;br /&gt;&lt;br /&gt;Viendo &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.davidcapello.com.ar/&quot;&gt;mi página&lt;/a&gt; hoy en día, siento que ya es una reliquia. Hace muchísimo que las páginas personales dejaron de existir como eran antes. Ahora son todos blogs, feeds, artículos, noticias, etc. Las viejas páginas personales (con secciones, site-map, etc.) ya son una antigüedad.&lt;br /&gt;&lt;br /&gt;A lo largo de los años fui quitando más y más texto de mi página, hasta dejarla pelada completamente. Hoy en día son sólo links, apuntando a otros sitios para bajarse cosas útiles (¿?). Algún que otro párrafo explicando algo, pero inclusive sospecho que esos párrafos nunca serán leídos.&lt;br /&gt;&lt;br /&gt;En fin, las viejas páginas personales fueron devoradas por la &quot;fast-food&quot; de la información en Internet.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-776387095377201992?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-776387095377201992</guid>
         <pubDate>Tue, 06 Oct 2009 18:16:00 -0700</pubDate>
      </item>
      <item>
         <title>Atajos del teclado de ErgoEmacs modificados para programar</title>
         <link>http://davidcapello.blogspot.com/2009/09/atajos-del-teclado-de-ergoemacs.html</link>
         <description>Después te conocer &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xahlee.org/emacs/ergonomic_emacs_keybinding.html&quot;&gt;ergoemacs&lt;/a&gt; no volví atrás. Aunque no del todo conforme con los atajos del teclado que ofrece por defecto, me abrió la cabeza para &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://github.com/dacap/dacap-dot-emacs&quot;&gt;personalizar Emacs a más no poder&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Acá dejo &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.davidcapello.com.ar/ergoemacs/dacap-keybindings.php&quot;&gt;mis atajos de teclado&lt;/a&gt; para programar. Básicamente son los de ErgoEmacs pero con leves modificaciones para mejorar la experiencia al programar (moverse por &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.gnu.org/software/emacs/manual/html_node/emacs/Expressions.html&quot;&gt;expresiones&lt;/a&gt; y moverse por &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.gnu.org/software/emacs/manual/html_node/emacs/Defuns.html&quot;&gt;funciones&lt;/a&gt;).&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-5646282094584873809?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-5646282094584873809</guid>
         <pubDate>Sat, 26 Sep 2009 14:07:00 -0700</pubDate>
      </item>
      <item>
         <title>From DLL- to XML-hell</title>
         <link>http://davidcapello.blogspot.com/2009/09/from-dll-to-xml-hell.html</link>
         <description>Un excelente artículo de Marek Krj:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ib-krajewski.blogspot.com/2009/04/from-dll-to-xml-hell.html&quot;&gt;http://ib-krajewski.blogspot.com/2009/04/from-dll-to-xml-hell.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Si alguna vez tuviste que configurar algo en Spring, vas a saber de qué está hablando el tipo.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-8744529879445879905?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-8744529879445879905</guid>
         <pubDate>Tue, 22 Sep 2009 02:37:00 -0700</pubDate>
      </item>
      <item>
         <title>Pixel Art/Dot Art Alive!</title>
         <link>http://aseprite.blogspot.com/2009/09/pixel-artdot-art-alive.html</link>
         <description>Take a look to the amazing &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://kofaniv.snkplaymore.co.jp/english/info/15th_anniv/2d_dot/index.php&quot;&gt;The King Of Fighter XII&lt;/a&gt;. Prerendered 3D models with pixel-art retouching, it looks great (more than 400 frames per character).&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-6491626077392168693?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-6491626077392168693</guid>
         <pubDate>Sat, 19 Sep 2009 14:51:00 -0700</pubDate>
      </item>
      <item>
         <title>Google Wave</title>
         <link>http://davidcapello.blogspot.com/2009/09/google-wave.html</link>
         <description>Una de las mejores cosas que vi:&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wave.google.com/&quot;&gt;http://wave.google.com/&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Google_Wave&quot;&gt;http://en.wikipedia.org/wiki/Google_Wave&lt;/a&gt;&lt;br /&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://code.google.com/intl/es-AR/apis/wave/&quot;&gt;http://code.google.com/intl/es-AR/apis/wave/&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-4607039804984917575?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-4607039804984917575</guid>
         <pubDate>Sat, 19 Sep 2009 14:26:00 -0700</pubDate>
      </item>
      <item>
         <title>ASE 0.7.2 Released</title>
         <link>http://aseprite.blogspot.com/2009/09/ase-072-released.html</link>
         <description>&lt;p&gt;&lt;b&gt;What is ASE?&lt;/b&gt;&lt;/p&gt;&lt;p&gt; ASE (&lt;b&gt;A&lt;/b&gt;llegro &lt;b&gt;S&lt;/b&gt;prite &lt;b&gt;E&lt;/b&gt;ditor) is an open source program to create animated sprites. Sprites are little images that can be used in your website or in a video game. You can draw characters with movement, intros, textures, patterns, backgrounds, logos, color palettes, isometric levels, etc.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;News in ASE 0.7.2&lt;/b&gt;&lt;br /&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Fixed bug #&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/tracker/index.php?func=detail&amp;amp;aid=2847210&amp;amp;group_id=20848&amp;amp;atid=120848&quot;&gt;2847210&lt;/a&gt;: &quot;Save&quot; button when close a modified file was not working.&lt;/li&gt; &lt;/ul&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.aseprite.org/&quot;&gt;http://www.aseprite.org/&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-6448588788763685015?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-6448588788763685015</guid>
         <pubDate>Fri, 04 Sep 2009 02:48:00 -0700</pubDate>
      </item>
      <item>
         <title>ASE 0.7.2 Released</title>
         <link>http://davidcapello.blogspot.com/2009/09/ase-072-released.html</link>
         <description>&lt;p&gt;ASE (Allegro Sprite Editor) is an open source program to create animated sprites. Sprites are little images that can be used in your website or in a video game. You can draw characters with movement, intros, textures, patterns, backgrounds, logos, color palettes, isometric levels, etc.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;News in ASE 0.7.2&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Fixed bug #2847210: &quot;Save&quot; button when close a modified file was not working.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;News in ASE 0.7.1&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Added &quot;Sprite Size&quot; command (feature #2671468).&lt;/li&gt;&lt;li&gt;Added &quot;Save Copy As&quot; command (feature #2636076).&lt;/li&gt;&lt;li&gt;Copy &amp;amp; Paste use Windows clipboard (feature #2577954).&lt;/li&gt;&lt;li&gt;Added &quot;Canvas Size&quot; and &quot;Rotate Canvas&quot; commands.&lt;/li&gt;&lt;li&gt;Fixed compilation support for gcc 64 bits.&lt;/li&gt;&lt;li&gt;Fixed a bug with multiple editors and paste command.&lt;/li&gt;&lt;li&gt;Fixed a bug in the File Open dialog when user presses ENTER key with an empty file name.&lt;/li&gt;&lt;li&gt;Fixed critical bugs in rendering code.&lt;/li&gt;&lt;li&gt;Added support to paste/copy text from/to Windows clipboard.&lt;/li&gt;&lt;li&gt;Added support to process Ctrl+C / Ctrl+V / Ctrl+P keys in all entry fields.&lt;/li&gt;&lt;li&gt;Fixed a bug where file names for new sprites are lower-case always (in Windows).&lt;/li&gt;&lt;li&gt;Fixed a program crash when try to open a file in the middle of a thumbnail generation process.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot;&gt;http:://www.aseprite.org/&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-4936948269997159937?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-4936948269997159937</guid>
         <pubDate>Fri, 04 Sep 2009 02:41:00 -0700</pubDate>
      </item>
      <item>
         <title>Modernización de Emacs</title>
         <link>http://davidcapello.blogspot.com/2009/08/modernizacion-de-emacs.html</link>
         <description>&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://xahlee.org/emacs/modernization.html&quot;&gt;Un artículo&lt;/a&gt; de Xah Lee que habla sobre cómo mejorar Emacs (por fin alguien que piensa en la usabilidad en el software libre).&lt;br /&gt;&lt;br /&gt;Y su proyecto para llevarlo a cabo: &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ergoemacs.org/&quot;&gt;ErgoEmacs&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-2441360825312396006?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-2441360825312396006</guid>
         <pubDate>Tue, 25 Aug 2009 17:22:00 -0700</pubDate>
      </item>
      <item>
         <title>ASE 0.7 Released</title>
         <link>http://aseprite.blogspot.com/2009/08/ase-07-released.html</link>
         <description>&lt;p&gt;&lt;b&gt;What is ASE?&lt;/b&gt;&lt;/p&gt;&lt;p&gt; ASE (&lt;b&gt;A&lt;/b&gt;llegro &lt;b&gt;S&lt;/b&gt;prite &lt;b&gt;E&lt;/b&gt;ditor) is an open source program to create animated sprites. Sprites are little images that can be used in your website or in a video game. You can draw characters with movement, intros, textures, patterns, backgrounds, logos, color palettes, isometric levels, etc.&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;b&gt;News in ASE 0.7&lt;/b&gt;&lt;br /&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Added &quot;Sprite Size&quot; command (feature &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/tracker/index.php?func=detail&amp;amp;aid=2671468&amp;amp;group_id=20848&amp;amp;atid=370848&quot;&gt;#2671468&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;Added &quot;Save Copy As&quot; command (feature &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/tracker/index.php?func=detail&amp;amp;aid=2636076&amp;amp;group_id=20848&amp;amp;atid=370848&quot;&gt;#2636076&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;Copy &amp;amp; Paste use Windows clipboard (feature &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/tracker/index.php?func=detail&amp;amp;aid=2577954&amp;amp;group_id=20848&amp;amp;atid=370848&quot;&gt;#2577954&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;Added &quot;Canvas Size&quot; and &quot;Rotate Canvas&quot; commands.&lt;/li&gt;&lt;li&gt;Fixed compilation support for gcc 64 bits.&lt;/li&gt;&lt;li&gt;Fixed a bug with multiple editors and paste command.&lt;/li&gt;&lt;li&gt;Fixed a bug in the File Open dialog when user presses ENTER key with an empty file name.&lt;/li&gt;&lt;li&gt;Fixed critical bugs in rendering code.&lt;/li&gt; &lt;/ul&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.aseprite.org/&quot;&gt;http://www.aseprite.org/&lt;/a&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-155462857336389426?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-155462857336389426</guid>
         <pubDate>Wed, 05 Aug 2009 03:43:00 -0700</pubDate>
      </item>
      <item>
         <title>Lo que Quieras Hacer</title>
         <link>http://davidcapello.blogspot.com/2009/07/lo-que-quieras-hacer.html</link>
         <description>Lo que Quieras Hacer&lt;br /&gt;Riff&lt;br /&gt;&lt;br /&gt;Te dicen que nunca hiciste algo bien,&lt;br /&gt;que no fuiste lo que debías ser;&lt;br /&gt;no saben que acaso no quisiste ser,&lt;br /&gt;como ellos decían estaba bien.&lt;br /&gt;&lt;br /&gt;Según pasa el tiempo te das cuenta que&lt;br /&gt;todo fue distinto a lo que iba a ser,&lt;br /&gt;sólo queda ahora seguir adelante,&lt;br /&gt;seguir adelante y no retroceder.&lt;br /&gt;&lt;br /&gt;Tuya, es toda tu vida&lt;br /&gt;para hacer lo que tu quieras hacer,&lt;br /&gt;tuya, y no sólo mía&lt;br /&gt;porque yo ya no te puedo ni ver.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-8475497203331026763?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-8475497203331026763</guid>
         <pubDate>Thu, 23 Jul 2009 14:18:00 -0700</pubDate>
      </item>
      <item>
         <title>C++0x no va a tener &quot;conceptos&quot;</title>
         <link>http://cmasomenos.blogspot.com/2009/07/c0x-no-va-tener-conceptos.html</link>
         <description>En la última reunión del &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.open-std.org/jtc1/sc22/wg21/&quot;&gt;ISO C++ Standards Committe&lt;/a&gt;e decidieron quitar los &quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Concepts_%28C%2B%2B0x%29&quot;&gt;conceptos&lt;/a&gt;&quot; del próximo estándar de &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/C%2B%2B0x&quot;&gt;C++&lt;/a&gt; (que en realidad, en vez de C++0x va a ser C++1x y chirola). &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ddj.com/architect/218600111&quot;&gt;Un artículo de Bjarne Stroustrup&lt;/a&gt; habla al respecto:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;[...] Básicamente, los &quot;conceptos&quot; tenían como meta hacer de la programación genérica algo más accesible a la mayoría de los programadores, pero esa meta ha sido para mí (Stroustrup) seriamente comprometida: En vez de hacer la programación genérica más accesible, los &quot;conceptos&quot; se fueron convirtiendo en otra herramienta más en las manos de los expertos (únicamente).&lt;br /&gt;[...]&lt;br /&gt;Para resumir y de alguna forma simplificar, he afirmado que:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Los &quot;conceptos&quot; como están actualmente definidos son muy difíciles de utilizar, lo que los llevará al desuso, dando la posibilidad a un desuso de los &lt;em&gt;templates&lt;/em&gt; mismos y a la adopción completa de C++0x.&lt;/li&gt;&lt;li&gt;Un pequeño conjunto de simplificaciones [&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2906.pdf&quot;&gt;BS2009&lt;/a&gt;] pueden dejar a los &quot;conceptos&quot; lo suficientemente aceptables como para salir acorde a las fechas planificadas para C++0x o con sólo un retraso menor.&lt;br /&gt;&lt;/ul&gt;[...] &lt;/blockquote&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-5568618301379444386?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-5568618301379444386</guid>
         <pubDate>Thu, 23 Jul 2009 04:10:00 -0700</pubDate>
      </item>
      <item>
         <title>ASE 0.7 in testing phase</title>
         <link>http://aseprite.blogspot.com/2009/07/ase-07-in-testing-phase.html</link>
         <description>This is a little video using ASE 0.7 in testing phase. You will see the usage of: split editors, mask selection, crop sprite, brush/line/curve/fill/jumble/blur tools, zoom, cut &amp; paste, color bar changes, etc.&lt;br /&gt;&lt;br /&gt;&lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://www.youtube.com/v/hHK65_9LB6k&amp;hl=en&amp;fs=1&amp;&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt; Music of &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.jamendo.com/album/35727&quot;&gt;JC PIERRIC&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-4900005825028894846?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-4900005825028894846</guid>
         <pubDate>Sat, 18 Jul 2009 02:55:00 -0700</pubDate>
      </item>
      <item>
         <title>STL vector en vez de los clásicos buffers de C</title>
         <link>http://cmasomenos.blogspot.com/2009/07/stl-vector-en-vez-de-los-clasicos.html</link>
         <description>Algunas veces tenemos que crear buffers temporales. Por ejemplo, la función &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/&quot;&gt;sprintf&lt;/a&gt; necesita de un buffer para poder dejar la cadena resultante. Ejemplo:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;char buf[256];&lt;br /&gt;sprintf(buf, &quot;%d&quot;, 12345);&lt;br /&gt;// usar &quot;buf&quot;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Si queremos mantener el buffer en heap:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;char* buf = malloc(256);&lt;br /&gt;sprintf(buf, &quot;%d&quot;, 12345);&lt;br /&gt;// usar &quot;buf&quot;...&lt;br /&gt;free(buf);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;En C++ podríamos hacer uso de los operadores new[]/delete[]:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;char* buf = new char[256];&lt;br /&gt;sprintf(buf, &quot;%d&quot;, 12345);&lt;br /&gt;// usar &quot;buf&quot;...&lt;br /&gt;delete[] buf;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Pero es aconsejable evitar la creación de arreglos con new[], y en su lugar hacer uso de &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/stl/vector/&quot;&gt;std::vector&lt;/a&gt;:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;std::vector&amp;lt;char&amp;gt; buf(256);&lt;br /&gt;sprintf(&amp;amp;buf[0], &quot;%d&quot;, 12345);&lt;br /&gt;// usar &quot;&amp;amp;buf[0]&quot; en vez de &quot;buf&quot;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;El resultado: tenemos un buffer en el heap que se libera automáticamente (~std::vector) al salir del ámbito de la función que lo utiliza.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-6330679899391627832?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-6330679899391627832</guid>
         <pubDate>Sun, 12 Jul 2009 07:01:00 -0700</pubDate>
      </item>
      <item>
         <title>Conscientemente todo todo lo podrás lograr</title>
         <link>http://davidcapello.blogspot.com/2009/04/conscientemente-todo-todo-lo-podras.html</link>
         <description>Conscientemente todo todo lo podrás lograr,&lt;br /&gt;Billy Bond y La Pesada Del Rock and Roll.&lt;br /&gt;&lt;blockquote&gt;En tu mente, en tu mente vivirán.&lt;br /&gt;Los deseos, los deseos de cambiar.&lt;br /&gt;Concientemente todo todo lo podrás lograr.&lt;br /&gt;&lt;br /&gt;No te quedes, no te quedes muy atrás.&lt;br /&gt;Si no sigues, no tendrás con quien hablar.&lt;br /&gt;Concientemente todo, todo lo podrás lograr.&lt;br /&gt;&lt;br /&gt;Vamos chicos, vamos chicos a cambiar.&lt;br /&gt;Vamos loco, vamos loco a cambiar.&lt;br /&gt;Concientemente todo todo lo podrás lograr.&lt;br /&gt;&lt;br /&gt;No te quedes siempre en el mismo lugar.&lt;br /&gt;Vamos chico, vamos loco a cambiar.&lt;br /&gt;Concientemente todo todo lo podrás lograr.&lt;br /&gt;&lt;/blockquote&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-2258902733151034586?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-2258902733151034586</guid>
         <pubDate>Mon, 06 Apr 2009 15:27:00 -0700</pubDate>
      </item>
      <item>
         <title>STL for_each</title>
         <link>http://cmasomenos.blogspot.com/2009/03/stl-foreach.html</link>
         <description>Para recorrer un arreglo de C, podemos utilizar punteros. Comenzamos apuntando al primer elemento y frenamos una vez procesado el último elemento:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; int array[] = { 5, 3, 4, 9, 1 };&lt;br /&gt; int array_size = sizeof(array) / sizeof(int); // cantidad de elementos de &quot;array&quot;&lt;br /&gt; int *array_begin = array; // comienzo del array&lt;br /&gt; int *array_end = array+array_size; // final del array (+un elemento)&lt;br /&gt; int *it; // el iterator&lt;br /&gt;&lt;br /&gt; for (it = array_begin; it != array_end; ++it) {&lt;br /&gt; printf(&quot;%d&amp;#92;n&quot;, *it);&lt;br /&gt; }&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Hay que tener en cuenta que array_end es igual a &amp;array[5]. Sabiendo que sólo podemos acceder a los elementos desde array[0] a array[4], decimos que array[5] está más allá del último elemento del arreglo, es decir, &amp;array[5] es la posición de memoria que ya no es parte del mismo arreglo (de ahí &quot;it != array_end&quot; significa &quot;mientras nos encontremos dentro del arreglo&quot;).&lt;br /&gt;&lt;br /&gt;¿Cómo recorrer un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sgi.com/tech/stl/Container.html&quot;&gt;contenedor&lt;/a&gt; de la STL? La idea es similar, sólo que en vez de usar punteros utilizamos iteradores, y observe como la sintaxis del &lt;i&gt;for&lt;/i&gt; es exactamente la misma. (nota: en este caso utilizamos un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sgi.com/tech/stl/Vector.html&quot;&gt;vector&lt;/a&gt;).&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; vector&amp;lt;int&amp;gt; array;&lt;br /&gt; array.push_back(5);&lt;br /&gt; array.push_back(3);&lt;br /&gt; array.push_back(4);&lt;br /&gt; array.push_back(9);&lt;br /&gt; array.push_back(1);&lt;br /&gt;&lt;br /&gt; vector&amp;lt;int&amp;gt;::iterator it;&lt;br /&gt;&lt;br /&gt; for (it = array.begin(); it != array.end(); ++it) {&lt;br /&gt; cout &amp;lt;&amp;lt; *it &amp;lt;&amp;lt; endl;&lt;br /&gt; }&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;¿Cómo recorrer un contenedor STL con el algoritmo &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sgi.com/tech/stl/for_each.html&quot;&gt;for_each&lt;/a&gt;? (nota: lo siguiente también se puede hacer con &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sgi.com/tech/stl/copy.html&quot;&gt;copy&lt;/a&gt; y &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sgi.com/tech/stl/ostream_iterator.html&quot;&gt;ostream_iterator&lt;/a&gt;)&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;void print_element(int a) { cout &amp;lt;&amp;lt; *it &amp;lt;&amp;lt; endl; }&lt;br /&gt; &lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; vector&amp;lt;int&amp;gt; array;&lt;br /&gt; array.push_back(5);&lt;br /&gt; array.push_back(3);&lt;br /&gt; array.push_back(4);&lt;br /&gt; array.push_back(9);&lt;br /&gt; array.push_back(1);&lt;br /&gt;&lt;br /&gt; for_each(array.begin(), array.end(), print_element);&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;La función pasada como tercer parámetro a &lt;i&gt;for_each&lt;/i&gt; es llamada por cada elemento del arreglo:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;template&lt;br /&gt; Function for_each(InputIterator first, InputIterator last, Function f)&lt;br /&gt;{&lt;br /&gt; for (; first != last; ++first)&lt;br /&gt; f(*first);&lt;br /&gt; return f;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;¿Por qué &lt;i&gt;for_each&lt;/i&gt; devuelve la función? Principalmente porque la función &quot;f&quot; podría no ser una función! Podría ser un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sgi.com/tech/stl/functors.html&quot;&gt;functor&lt;/a&gt; (objeto función), es decir, una instancia de una clase que tiene sobrecargado el &lt;i&gt;operator()&lt;/i&gt; (llamada a función). Pero este tema se merece su propio post.&lt;br /&gt;&lt;br /&gt;¿Se puede usar el algoritmo for_each para los arreglos de C? Sí.&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;void print_element(int a) { printf(&quot;%d&amp;#92;n&quot;, a); }&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; int array[] = { 5, 3, 4, 9, 1 };&lt;br /&gt; int array_size = sizeof(array) / sizeof(int); // cantidad de elementos de &quot;array&quot;&lt;br /&gt; int *array_begin = array; // comienzo del array&lt;br /&gt; int *array_end = array+array_size; // final del array (un elemento más)&lt;br /&gt;&lt;br /&gt; for_each(array_begin, array_end, print_element);&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-6782049308008941622?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-6782049308008941622</guid>
         <pubDate>Sat, 21 Mar 2009 01:44:00 -0700</pubDate>
      </item>
      <item>
         <title>Musics in Jamendo</title>
         <link>http://davidcapello.blogspot.com/2009/01/musics-in-jamendo.html</link>
         <description>Now you have &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.jamendo.com/es/artist/David_Capello&quot;&gt;a place&lt;/a&gt; to curse my &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.davidcapello.com.ar/musics/&quot;&gt;musics&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3678361980191086929-2919486794922615469?l=davidcapello.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3678361980191086929.post-2919486794922615469</guid>
         <pubDate>Thu, 29 Jan 2009 03:47:00 -0800</pubDate>
      </item>
      <item>
         <title>STL generate</title>
         <link>http://cmasomenos.blogspot.com/2008/12/stl-generate.html</link>
         <description>Si usted tiene una función que genera números/valores/instancias (ej: un generador de números aleatorios, o identificadores) puede usar el algoritmo &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/reference/algorithm/generate.html&quot;&gt;generate&lt;/a&gt; de la &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sgi.com/tech/stl/&quot;&gt;STL&lt;/a&gt; para crear una secuencia de objetos. Por ejemplo, para generar 100 números (pseudo)aleatorios de 0 a 1:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;#include &amp;lt;vector&amp;gt;&lt;br /&gt;&lt;br /&gt;double uniform_random()&lt;br /&gt;{&lt;br /&gt; return (rand() % 10001) / 10000.0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; std::vector&amp;lt;double&amp;gt; v(100);&lt;br /&gt; std::generate(v.begin(), v.end(), uniform_random);&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;El algoritmo &lt;em&gt;generate&lt;/em&gt; recibe dos iteradores (inicio y fin), y llama a la función especificada para cada una de las posiciones que recorre:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;template&amp;lt;typename ForwardIterator, typename Generator&amp;gt;&lt;br /&gt;void generate(ForwardIterator first, ForwardIterator last,&lt;br /&gt; Generator gen)&lt;br /&gt;{&lt;br /&gt; for (; first != last; ++first)&lt;br /&gt; *first = gen();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Los algoritmos de la STL son genéricos porque utilizan la &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Pointer_(computing)#C_and_C.2B.2B&quot;&gt;aritmética de punteros&lt;/a&gt;. Los iteradores sobrecargan los operadores para poder ser utilizados como punteros. Así un algoritmo puede ser utilizado con los contenedores de la STL (&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.sgi.com/tech/stl/Vector.html&quot;&gt;vector&lt;/a&gt;) o con los viejos y tan queridos arreglos (y punteros) de C:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;algorithm&amp;gt;&lt;br /&gt;&lt;br /&gt;double uniform_random()&lt;br /&gt;{&lt;br /&gt; return (rand() % 10001) / 10000.0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; double v[100];&lt;br /&gt; std::generate(v, v+100, uniform_random);&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-8017999882907419607?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-8017999882907419607</guid>
         <pubDate>Mon, 08 Dec 2008 06:18:00 -0800</pubDate>
      </item>
      <item>
         <title>¿Preincrementar o postincrementar?</title>
         <link>http://cmasomenos.blogspot.com/2008/08/preincrementar-o-postincrementar.html</link>
         <description>Hace mucho que quería escribir un post tan inútil como este. La duda que siempre me pasaba por la cabeza era la siguiente: ¿Será exactamente el mismo código ensamblador el que genera el compilador cuando utilizamos el preincremento o el postincremento (sin utilizar el valor de retorno)? Tenía la seguridad de que así debía ser (una optimización tan básica no podía ser dejada de lado), pero me faltaban las pruebas (en ensamblador) para verificarlo.&lt;br /&gt;&lt;br /&gt;Recordando un poco, el preincremento&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;int a = 0;&lt;br /&gt;int b = ++a;&lt;br /&gt;&lt;/pre&gt;hace &lt;i&gt;a=1&lt;/i&gt; y &lt;i&gt;b=1&lt;/i&gt;, mientras que el postincremento&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;int a = 0;&lt;br /&gt;int b = a++;&lt;br /&gt;&lt;/pre&gt;hace &lt;i&gt;a=1&lt;/i&gt; y &lt;i&gt;b=0&lt;/i&gt;, esto significa que &lt;i&gt;b&lt;/i&gt; obtuvo el valor de &lt;i&gt;a&lt;/i&gt; anterior al incremento.&lt;br /&gt;&lt;br /&gt;Aquí &lt;i&gt;estamos utilizando&lt;/i&gt; el valor de retorno del operador incremento. El código ensamblador &lt;i&gt;es distinto&lt;/i&gt; para cada caso. Vamos a echarle una mirada (antes le recomiendo ver &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.unixwiz.net/techtips/win32-callconv-asm.html&quot;&gt;este excelente artículo&lt;/a&gt; para comprender más sobre el stack y las convenciones de llamadas). En el preincremento el código ensamblador (generado por GCC 3.4.5 para i386) es:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;subl $8, %esp // reservamos 8 bytes en el &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Call_stack&quot;&gt;stack&lt;/a&gt; (para variables locales)&lt;br /&gt;movl $0, -4(%ebp) // a = 0&lt;br /&gt;leal -4(%ebp), %eax // eax = &amp;amp;a&lt;br /&gt;incl (%eax) // *eax= (*eax) + 1&lt;br /&gt;movl -4(%ebp), %eax // eax = a&lt;br /&gt;movl %eax, -8(%ebp) // b = eax&lt;br /&gt;&lt;/pre&gt;En el postincremento&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;subl $8, %esp // reservamos 8 bytes en el stack&lt;br /&gt;movl $0, -4(%ebp) // a = 0&lt;br /&gt;movl -4(%ebp), %edx // edx = a&lt;br /&gt;leal -4(%ebp), %eax // eax = &amp;amp;a&lt;br /&gt;incl (%eax) // *eax= (*eax) + 1&lt;br /&gt;movl %edx, -8(%ebp) // b = edx&lt;/pre&gt;donde se ve que el registro edx se utiliza para guardar el valor que tenía &lt;i&gt;a&lt;/i&gt; antes del incremento para luego asignárselo a &lt;i&gt;b&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Pero la pregunta original es, ¿qué pasa si &lt;b&gt;no&lt;/b&gt; usamos el valor de retorno? ¿el código de ++i o i++ es igual? Debería serlo, y de hecho, lo es. Pero como veremos más abajo, esto sólo se cumple si utilizamos tipos de datos &lt;i&gt;built-in&lt;/i&gt; (int, double, long, etc.). Miremos el siguiente código:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;void func() { }&lt;br /&gt;void pre () { for (int c=0; c&amp;lt;8; ++c) { func(); } }&lt;br /&gt;void post() { for (int c=0; c&amp;lt;8; c++) { func(); } }&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; pre();&lt;br /&gt; post();&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Básico, un &lt;i&gt;for&lt;/i&gt; pero con las dos variantes posible de incremento. El código generado para ambos casos (tanto para la función &lt;i&gt;pre&lt;/i&gt; como &lt;i&gt;post&lt;/i&gt;) es el siguiente:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;br /&gt; pushl %ebp // guardar el viejo puntero a la base del stack&lt;br /&gt; movl %esp, %ebp // establecer la nueva base del stack&lt;br /&gt; subl $4, %esp // guardar 4 bytes en el stack (para variables locales)&lt;br /&gt; movl $0, -4(%ebp) // c = 0&lt;br /&gt;L3:&lt;br /&gt; cmpl $7, -4(%ebp)&lt;br /&gt; jg L2 // si c &amp;gt; 7 entonces ir a L2&lt;br /&gt; call _func // llamar a la función func()&lt;br /&gt; leal -4(%ebp), %eax // eax = &amp;amp;c&lt;br /&gt; incl (%eax) // *eax= (*eax) + 1&lt;br /&gt; jmp L3 // repetir yendo a L3&lt;br /&gt;L2:&lt;br /&gt; leave // restaurar la base del stack (popl %ebp)&lt;br /&gt; ret // retornar al punto de llamada&lt;br /&gt;&lt;/pre&gt;Realmente es indiferente usar cualquiera de los dos tipos de incremento, salvo, en los tipos definidos por el usuario. C++ ofrece un soporte para tipos de usuario igual a los built-in (bueno, no del todo, pero &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.artima.com/cppsource/cpp0xP.html&quot;&gt;lo están solucionando&lt;/a&gt;). Nos da la posibilidad de sobrecargar los operadores de nuestros propios tipos (clases). Por ejemplo:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;class tipo {&lt;br /&gt; int x;&lt;br /&gt;public:&lt;br /&gt; tipo(int y) : x(y) { }&lt;br /&gt; tipo(const tipo&amp;amp; y) : x(y.x) { }&lt;br /&gt; // preincremento&lt;br /&gt; tipo&amp;amp; operator++() {&lt;br /&gt; ++x;&lt;br /&gt; return *this;&lt;br /&gt; }&lt;br /&gt; // postincremento&lt;br /&gt; tipo operator++(int) {&lt;br /&gt; tipo tmp(*this);&lt;br /&gt; ++x;&lt;br /&gt; return tmp;&lt;br /&gt; }&lt;br /&gt; bool operator&amp;lt;(int y) const { return x &amp;lt; y; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;void func() { }&lt;br /&gt;void pre() { for (tipo c=0; c&amp;lt;8; ++c) { func(); } }&lt;br /&gt;void post() { for (tipo c=0; c&amp;lt;8; c++) { func(); } }&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt; post();&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;No colocaré el código ensamblador por desbordar belleza, pero el código generado en este caso es distinto: cada incremento llama a la función correspondiente a su operador. Esto es debido a que ambas implementaciones varían considerablemente. Por ejemplo, el postincremento necesita de una instancia extra de &lt;i&gt;tipo&lt;/i&gt; para poder devolver el anterior valor de &lt;i&gt;this&lt;/i&gt;, en cambio, el preincremento devuelve una referencia al mismo &lt;i&gt;this&lt;/i&gt; (sin necesidad de hacer una copia).&lt;br /&gt;&lt;br /&gt;Como dato curioso, algo interesante ocurre al utilizar las optimizaciones del GCC. Si compilamos este último programa con el parámetro -O3, vamos a ver que todas las funciones correspondientes a la clase &lt;i&gt;tipo&lt;/i&gt; desaparecen, y todo el código resultantes es &lt;i&gt;inline&lt;/i&gt;, dando como resultado un código tan óptimo como si hubiéramos utilizado un &lt;i&gt;int&lt;/i&gt; en vez de nuestra clase &lt;i&gt;tipo&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;¿Cómo obtengo el código ensamblador desde un archivo C/C++?&lt;/b&gt;&lt;br /&gt;Con el compilador &lt;i&gt;gcc&lt;/i&gt;, hay que utilizar el parámetro -S: &lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;g++ -S -o archivo.s -c archivo.cpp&lt;br /&gt;&lt;/pre&gt;En &lt;i&gt;archivo.s&lt;/i&gt; queda el código ensamblador (sintaxis &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com.ar/search?q=AT%26T+Assembly+Syntax&quot;&gt;AT&amp;amp;T&lt;/a&gt;).&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-4871056687622874222?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-4871056687622874222</guid>
         <pubDate>Tue, 19 Aug 2008 02:34:00 -0700</pubDate>
      </item>
      <item>
         <title>Excepciones, RAII y auto_ptr</title>
         <link>http://cmasomenos.blogspot.com/2008/06/excepciones-raii-y-autoptr.html</link>
         <description>Una de las mejores formas de realizar un control de errores es por medio de excepciones. Lamentablemente, si no se toman las precauciones adecuadas, se pueden obtener &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Handle_leak&quot;&gt;leaks&lt;/a&gt; de algunos recursos. Por ejemplo, imagine el siguiente caso:&lt;pre class=&quot;prettyprint&quot;&gt;int main()&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;try {&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;char *ptr = new char[256];&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;double *matrix = new double[100000*100000]; // 74 Gigabytes&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;// ...&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;delete matrix;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;delete ptr;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;} catch (const std::bad_alloc&amp;amp; e) {&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;std::cout &amp;lt;&amp;lt; &quot;No hay memoria suficiente&quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;}&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Aquí, con el segundo &lt;em&gt;new&lt;/em&gt; una excepción &lt;em&gt;bad_alloc&lt;/em&gt; es lanzada. El problema es que la memoria asignada con el primer &lt;em&gt;new&lt;/em&gt; nadie la libera. Esto es un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Memory_leak&quot;&gt;memory leak&lt;/a&gt;. Una opción para solucionarlo es mediante un bloque &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.research.att.com/~bs/bs_faq2.html#finally&quot;&gt;finally&lt;/a&gt; &quot;a la Java&quot;:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;int main()&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;char *ptr = NULL;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;double *matrix = NULL;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;try {&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;ptr = new char[256];&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;matrix = new double[100000*100000];&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;// ...&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;delete matrix;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;delete ptr;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;} catch (...) { // finally&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;if (matrix) delete matrix;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;if (ptr) delete ptr;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;}&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Claro que esto no hace al manejo de errores una tarea transparente.&lt;br /&gt;&lt;br /&gt;En C++ se puede utilizar la técnica &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization&quot;&gt;RAII&lt;/a&gt; (la adquisición de recursos está en la inicialización), lo que ayuda a evitar &lt;em&gt;leaks&lt;/em&gt;. La idea básica detrás de esto es que los constructores obtengan recursos, y los destructores los liberen. Al ocurrir una excepción, se van llamando los destructores de los objetos creados.&lt;br /&gt;&lt;br /&gt;Para solucionar nuestro problema, podemos utilizar la clase &lt;em&gt;auto_ptr&lt;/em&gt; que se encuentra en &amp;lt;memory&amp;gt;. Un &lt;em&gt;auto_ptr&lt;/em&gt; guarda un puntero que es liberado automáticamente en el destructor.&lt;pre class=&quot;prettyprint&quot;&gt;int main()&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;try {&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;std::auto_ptr&amp;lt;char&amp;gt; ptr(new char[256]);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;std::auto_ptr&amp;lt;double&amp;gt; matrix(new double[100000*100000]);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;// ...&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;} catch (const std::bad_alloc&amp;amp; e) {&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;std::cout &amp;lt;&amp;lt; &quot;No hay memoria suficiente&quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;}&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Los &lt;em&gt;delete&lt;/em&gt;s no son necesarios. Al salir del &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Scope_%28programming%29&quot;&gt;ámbito&lt;/a&gt; del bloque &lt;em&gt;try&lt;/em&gt;, ya sea normalmente o por excepción, se llamará al destructor de los &lt;em&gt;auto_ptr&lt;/em&gt;s creados, así no se incurre en ningún tipo de &lt;em&gt;leak&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Advertencia&lt;/b&gt;: Los &lt;em&gt;auto_ptr&lt;/em&gt; deben ser utilizados sabiendo cuál es su verdadero funcionamiento: La copia de un &lt;em&gt;auto_ptr&lt;/em&gt; a otro no los deja equivalentes. La última copia se queda con el puntero, los demás lo van perdiendo, y el &lt;em&gt;delete&lt;/em&gt; lo invoca el último &lt;em&gt;auto_ptr&lt;/em&gt; destruido. Por ejemplo:&lt;pre class=&quot;prettyprint&quot;&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;std::auto_ptr&amp;lt;Persona&amp;gt; otra_persona;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;std::auto_ptr&amp;lt;Persona&amp;gt; una_persona(new Persona);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;otra_persona = una_persona;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;// ahora &quot;una_persona&quot; apunta a NULL&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;}&lt;br /&gt;} // aquí la persona es destruida&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Pregunta&lt;/b&gt;: ¿Por qué no usar objetos alojados en el &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Call_stack&quot;&gt;stack&lt;/a&gt; en vez del &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Dynamic_memory_allocation&quot;&gt;heap&lt;/a&gt; para evitar los &lt;em&gt;leaks&lt;/em&gt;? Porque el &lt;em&gt;stack&lt;/em&gt; es mucho más pequeño. Por ejemplo, el siguiente código provoca un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/SIGSEGV&quot;&gt;SIGSEGV&lt;/a&gt; ya que el arreglo no entra en el &lt;em&gt;stack&lt;/em&gt;:&lt;pre class=&quot;prettyprint&quot;&gt;double matrix[1000000];&lt;/pre&gt;Pero sí entra en el &lt;em&gt;heap&lt;/em&gt;:&lt;pre class=&quot;prettyprint&quot;&gt;double *matrix = new double[1000000]; // 7.6 Megabytes&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-1607696112932338525?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-1607696112932338525</guid>
         <pubDate>Tue, 24 Jun 2008 08:28:00 -0700</pubDate>
      </item>
      <item>
         <title>Multiple editors</title>
         <link>http://aseprite.blogspot.com/2008/06/multiple-editors.html</link>
         <description>This video shows how to configure the screen to edit a sprite with multiple editors (you can use the shortcuts Ctrl+1, Ctrl+2, Ctrl+3, Ctrl+4 to see what happen).&lt;br /&gt;&lt;br /&gt;   &lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://www.youtube.com/v/vHXdOLa2CiE&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;350&quot;&gt; &lt;/iframe&gt; &lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-8891353166154906775?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-8891353166154906775</guid>
         <pubDate>Tue, 03 Jun 2008 07:27:00 -0700</pubDate>
      </item>
      <item>
         <title>First look at the Animation Editor - Frame properties</title>
         <link>http://aseprite.blogspot.com/2008/05/first-look-at-animation-editor-frame.html</link>
         <description>Here you will see how to add frames using the menus and then with the N key (&lt;em&gt;New Frame&lt;/em&gt;). Also I used the Ctrl+B shortcut to do Edit/Clear (clear the entire cel), because when you add a new frame a copy of the current one is made to the next new frame. You can enter to the Animation Editor with the TAB key.&lt;br /&gt;&lt;br /&gt;&lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://www.youtube.com/v/ICBcE4vAjYY&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;350&quot;&gt;&lt;/iframe&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-8415668041104709826?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-8415668041104709826</guid>
         <pubDate>Mon, 12 May 2008 02:32:00 -0700</pubDate>
      </item>
      <item>
         <title>Compilando archivos</title>
         <link>http://cmasomenos.blogspot.com/2008/05/compilando-archivos.html</link>
         <description>Suponiendo que conoce qué es un archivo de &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/C%C3%B3digo_fuente&quot;&gt;código fuente&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/C%C3%B3digo_objeto&quot;&gt;código objeto&lt;/a&gt;, un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/Ejecutable&quot;&gt;ejecutable&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/EXE&quot;&gt;&lt;b&gt;.exe&lt;/b&gt;&lt;/a&gt;, y el &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/C%C3%B3digo_m%C3%A1quina&quot;&gt;código máquina&lt;/a&gt;; voy a pasar a explicar algunos comandos del &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/GCC&quot;&gt;GCC&lt;/a&gt; para compilar.&lt;br /&gt;&lt;br /&gt;Retomando la idea del &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://cmasomenos.blogspot.com/2008/03/medir-el-tiempo-de-una-rutina.html&quot;&gt;anterior post&lt;/a&gt;, imagínese que creamos un archivo &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://davidcapello.googlepages.com/timemark.h&quot;&gt;timemark.h&lt;/a&gt; para darle un poco de portabilidad a todo este asunto de medir el desempeño de una rutina. Las declaraciones de timemark.h pueden ser usadas para crear un pequeño programa &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://davidcapello.googlepages.com/ejemplo1.c&quot;&gt;ejemplo1.c&lt;/a&gt; que sea independiente de la plataforma (por lo menos entre Windows y GNU/Linux).&lt;br /&gt;&lt;br /&gt;Vamos a probar algunas operaciones sobre la línea de comandos para ver cómo compilar este archivo. Inicialmente, la opción más sencilla es utilizar directamente &quot;gcc ejemplo1.c&quot;, esto nos da como resultado el archivo &quot;a.exe&quot; o &quot;a.out&quot;. Veamos (teniendo &lt;em&gt;timemark.h&lt;/em&gt; y &lt;em&gt;ejemplo1.c&lt;/em&gt; en un directorio &lt;em&gt;C:&amp;#92;ejemplo1&lt;/em&gt;):&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;C:&amp;#92;ejemplo1&amp;gt;gcc ejemplo1.c&lt;br /&gt;C:/Temp/ccMjdaaa.o:ejemplo1.c:(.text+0x31): undefined reference to `get_timemark'&lt;br /&gt;C:/Temp/ccMjdaaa.o:ejemplo1.c:(.text+0x3c): undefined reference to `get_timemark'&lt;br /&gt;C:/Temp/ccMjdaaa.o:ejemplo1.c:(.text+0x4e): undefined reference to `timemark_diff'&lt;br /&gt;collect2: ld returned 1 exit status&lt;br /&gt;&lt;/pre&gt;Como podrá ver, recibimos un error por las funciones no definidas &lt;em&gt;get_timermark&lt;/em&gt; y &lt;em&gt;timemark_diff&lt;/em&gt;. Esto se debe a que utilizando solamente &quot;gcc ejemplo1.c&quot;, se intenta enlazar el código de ese único archivo en el ejecutable. Tenemos algunas opciones intermedias antes de crear el .exe final. Por ejemplo, podemos crear un archivo que contenga el código objeto ya compilado (pero únicamente del archivo en cuestión &lt;em&gt;ejemplo1.c&lt;/em&gt;):&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;C:&amp;#92;ejemplo1&amp;gt;gcc -o ejemplo1.o -c ejemplo1.c&lt;br /&gt;&lt;/pre&gt;Así obtenemos el &lt;em&gt;ejemplo1.o&lt;/em&gt; (código objeto). En este caso no recibimos errores ya que &lt;em&gt;ejemplo1.o&lt;/em&gt; hace referencias a las funciones &lt;em&gt;get_timermark&lt;/em&gt; y &lt;em&gt;timemark_diff&lt;/em&gt;, pero no necesita su implementación específica. Cuando creamos el ejecutable final (&lt;em&gt;.exe&lt;/em&gt;) es cuando realmente necesitamos el código de todas las funciones invocadas.&lt;br /&gt;&lt;br /&gt;El archivo que falta es &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://davidcapello.googlepages.com/timemark.c&quot;&gt;timemark.c&lt;/a&gt;. Del mismo modo, podemos compilarlo con el comando:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;C:&amp;#92;ejemplo1&amp;gt;gcc -o timemark.o -c timemark.c&lt;br /&gt;&lt;/pre&gt;Ahora resta unir ambos archivos objetos en un único ejecutable, con un único punto de acceso (&lt;em&gt;main&lt;/em&gt;):&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;C:&amp;#92;ejemplo1&amp;gt;gcc -o ejemplo.exe ejemplo1.o timemark.o&lt;br /&gt;&lt;/pre&gt;Y listo. Por ahora, lo aprendido son estos dos comandos:&lt;br /&gt;&lt;pre class=&quot;source-code&quot;&gt;gcc -o archivo.o -c archivo.c&lt;br /&gt;gcc -o archivo.exe archivo1.o archivo2.o archivo3.o ...&lt;br /&gt;&lt;/pre&gt;El primero compila el código fuente para generar un archivo objeto, y el segundo comando reune (enlaza, &lt;em&gt;linkea&lt;/em&gt;) el grupo de archivos objetos en un ejecutable único.&lt;br /&gt;&lt;br /&gt;De todas formas, es bastante tedioso escribir estos comandos cada vez que queremos compilar. Para resolver el problema podemos utilizar los llamados Makefiles. Claro, lo más interesante queda para un futuro post.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-9220110933263076450?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-9220110933263076450</guid>
         <pubDate>Fri, 09 May 2008 17:30:00 -0700</pubDate>
      </item>
      <item>
         <title>Chaging the grid bounds</title>
         <link>http://aseprite.blogspot.com/2008/05/chaging-grid-bounds.html</link>
         <description>To change the bounds of the grid you have to select a rectangular area with the &lt;em&gt;Rectangular Marquee&lt;/em&gt; tool (M key) and then click the &quot;Set Grid&quot; button in the &lt;em&gt;Tools Configuration&lt;/em&gt; dialog (C key to show/hide this dialog).&lt;br /&gt;&lt;br /&gt;&lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://www.youtube.com/v/bqSz0Xsykak&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;350&quot;&gt;&lt;/iframe&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-6204320322593934107?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-6204320322593934107</guid>
         <pubDate>Fri, 09 May 2008 08:10:00 -0700</pubDate>
      </item>
      <item>
         <title>Using the Color Bar</title>
         <link>http://aseprite.blogspot.com/2008/05/using-color-bar.html</link>
         <description>Here you can see how to change the Foreground &amp; Background colors. Mainly, you will see that changing the first or last color of the Color Bar's range, you can make gradients. Here I used the left mouse button to pick the Foreground color from other slots in the Color Bar, and the Shift and Ctrl keys to select ranges in the color selector's palette.&lt;br /&gt;&lt;br /&gt;   &lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://www.youtube.com/v/SsiQuNZ32Cc&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;350&quot;&gt; &lt;/iframe&gt; &lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-6176888071554540339?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-6176888071554540339</guid>
         <pubDate>Thu, 08 May 2008 03:52:00 -0700</pubDate>
      </item>
      <item>
         <title>Changing the Pixel Scaling factor</title>
         <link>http://aseprite.blogspot.com/2008/05/changing-pixel-scaling-factor.html</link>
         <description>By default, ASE starts with a Pixel Scaling of x2 (on Windows, on GNU/Linux it starts with x1). If you see that the program is really slow with x2, then you can change the Pixel Scaling to the normal size (x1), so you can get a really good improvement in speed:&lt;br /&gt;&lt;br /&gt;   &lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://www.youtube.com/v/t8szx_YioT8&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;350&quot;&gt; &lt;/iframe&gt; &lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-1241036150440537415?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-1241036150440537415</guid>
         <pubDate>Wed, 07 May 2008 04:16:00 -0700</pubDate>
      </item>
      <item>
         <title>Drawing a little sprite (one frame, one layer)</title>
         <link>http://aseprite.blogspot.com/2008/05/drawing-little-sprite-one-frame-one.html</link>
         <description>This is the first video I'm publishing. Here I draw a little sprite using these tools:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the &lt;em&gt;Pencil&lt;/em&gt; tool (B key),&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the &lt;em&gt;Paint Bucket&lt;/em&gt; tool (G key),&lt;/li&gt;&lt;br /&gt;&lt;li&gt;and the &lt;em&gt;Blur&lt;/em&gt; tool (R key).&lt;/li&gt;&lt;/ul&gt;Also I use the &lt;em&gt;Rectangular Marquee&lt;/em&gt; (M key) and &lt;em&gt;Crop&lt;/em&gt; command to make the sprite bigger. Furthermore, you will see a intensive use of the zoom with the 1, 2, 3, 4, 5 and 6 keys. About the colors, see that I change (&lt;em&gt;Eye dropper&lt;/em&gt; with Alt+Left button) only the Foreground color, the Background color is always white.&lt;br /&gt;&lt;br /&gt;   &lt;iframe class=&quot;embeddedvideo&quot; src=&quot;http://www.youtube.com/v/wlGLrcDsZv0&quot; type=&quot;application/x-shockwave-flash&quot; width=&quot;425&quot; height=&quot;350&quot;&gt; &lt;/iframe&gt; &lt;br /&gt; Tip: you can draw sprites in black and white, if it looks &quot;good&quot;, then you add the color.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3721540033811045024-1855181925696919956?l=aseprite.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-3721540033811045024.post-1855181925696919956</guid>
         <pubDate>Tue, 06 May 2008 09:59:00 -0700</pubDate>
      </item>
      <item>
         <title>Medir el tiempo de una rutina</title>
         <link>http://cmasomenos.blogspot.com/2008/03/medir-el-tiempo-de-una-rutina.html</link>
         <description>¿Alguna vez se preocupó por la velocidad con la que corre su programa? ¿No? Entonces usted es un candidato perfecto para jugar al &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Java_%28board_game%29&quot;&gt;Java&lt;/a&gt;. En caso contrario, voy a explicarle un pequeño código que utilizaremos en próximas entregas para medir el tiempo de ejecución de determinadas rutinas.&lt;br /&gt;&lt;br /&gt;Ya lo dijo &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://shreevatsa.wordpress.com/2008/05/16/premature-optimization-is-the-root-of-all-evil/&quot;&gt;alguien&lt;/a&gt;: &quot;La optimización prematura es la raíz de todos los males&quot;. No hay nada más cierto, aunque también es verdad que hacer algo simple de la peor forma posible, es la causa de &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.urbandictionary.com/define.php?term=pain+in+the+ass&quot;&gt;otros grandes males&lt;/a&gt;. Con esto quiero decir que debería intentar hacer las cosas de la forma más simple y más óptima que usted conozca (dándole mayor importancia a la simplicidad del código); luego se preocupa por &quot;darle velocidad&quot; a la rutina que provoca el cuello de botella (en próximos posts veremos cómo usar &lt;em&gt;gprof&lt;/em&gt; para detectarlo).&lt;br /&gt;&lt;br /&gt;La forma de calcular el tiempo de CPU que toma una función es muy simple:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;tomamos el valor del reloj antes de realizar la llamada (&lt;em&gt;t_ini&lt;/em&gt;),&lt;/li&gt;&lt;li&gt;llamamos a la rutina en cuestión, y&lt;/li&gt;&lt;li&gt;tomamos nuevamente el valor del reloj (&lt;em&gt;t_fin&lt;/em&gt;).&lt;/li&gt;&lt;/ul&gt;La diferencia entre &lt;em&gt;t_fin - t_ini&lt;/em&gt; nos da el total de tiempo que tomó: 1) hacer la llamada a la rutina, 2) que esta haga su trabajo, 3) que devuelva el resultado.&lt;br /&gt;&lt;br /&gt;Ahora hay algunos pequeños detalles de implementación. Por ejemplo, ¿qué función usar para tomar el tiempo del reloj? Y más importante, ¿qué precisión obtenemos con dicha función?&lt;br /&gt;&lt;br /&gt;Para tomar el tiempo podemos usar la rutina &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/clock&quot;&gt;clock()&lt;/a&gt;, que devuelve el tiempo &lt;em&gt;aproximado&lt;/em&gt; de CPU que transcurrió desde que nuestro programa fue iniciado, dicho tiempo representado en un valor de tipo &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/clock_t&quot;&gt;clock_t&lt;/a&gt;: un valor entero que indica una cantidad de &quot;tics&quot; de reloj.&lt;br /&gt;&lt;br /&gt;La precisión que tenemos con dicha rutina es de &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.cplusplus.com/CLOCKS_PER_SEC&quot;&gt;CLOCKS_PER_SEC&lt;/a&gt; (tics de reloj por segundo), lo que significa que por cada segundo que pasa, la función &lt;em&gt;clock()&lt;/em&gt; nos devolverá CLOCKS_PER_SEC unidades más que el valor anterior. En MinGW, CLOCKS_PER_SEC es igual a 1000, pero es mejor no fiarse de esto, ya que en otras plataformas dicho valor varía. Inclusive, según POSIX, la constante CLOCKS_PER_SEC debería ser 1000000.&lt;br /&gt;&lt;br /&gt;Veamos algo de código:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;time.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;clock_t t_ini, t_fin;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;double secs;&lt;br /&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;t_ini = clock();&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;/* ...hacer algo... */&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;t_fin = clock();&lt;br /&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;secs = (double)(t_fin - t_ini) / CLOCKS_PER_SEC;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;printf(&quot;%.16g milisegundos&amp;#92;n&quot;, secs * 1000.0);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Con esto podemos medir cuántos milisegundos demoró &lt;em&gt;&quot;hacer algo&quot;&lt;/em&gt;. Todo parece muy bonito hasta que nos damos cuenta de dos grandes problemas:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Tomar una medida única y aislada es igual que tomar un número completamente aleatorio y mostrarlo (no es una &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/Muestra_estad%C3%ADstica&quot;&gt;muestra representativa&lt;/a&gt;). Es mejor repetir las mediciones unas cuantas veces (y hablo del orden de las 100, o 100000, o 1e32 veces), y luego sacar un promedio de todo.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;La función &lt;span style=&quot;font-style:italic;&quot;&gt;clock()&lt;/span&gt; no llega a tener una precisión ni de 10 milisegundos (aunque CLOCS_PER_SEC sea 1000 o más).&lt;/li&gt;&lt;/ol&gt;Una vez dicho esto, el código de arriba no sirve ni para &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/Papel_higi%C3%A9nico&quot;&gt;limpiarse&lt;/a&gt; los &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/Traste&quot;&gt;trastes&lt;/a&gt;... Así que tenemos que buscar una función con mayor precisión, y además, promediar varias muestras.&lt;br /&gt;&lt;br /&gt;Existen otras alternativas como la función &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.freebsd.org/cgi/man.cgi?query=gettimeofday&quot;&gt;gettimeofday&lt;/a&gt;, pero bajo Windows sufre del mismo problema de precisión que &lt;em&gt;clock()&lt;/em&gt;. Igualmente en Linux funciona perfectamente, así que vale la pena tener en cuenta este código:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;time.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/time.h&amp;gt;&lt;br /&gt;&lt;br /&gt;/* retorna &quot;a - b&quot; en segundos */&lt;br /&gt;double timeval_diff(struct timeval *a, struct timeval *b)&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;return&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;(double)(a-&amp;gt;tv_sec + (double)a-&amp;gt;tv_usec/1000000) -&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;(double)(b-&amp;gt;tv_sec + (double)b-&amp;gt;tv_usec/1000000);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;struct timeval t_ini, t_fin;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;double secs;&lt;br /&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;gettimeofday(&amp;amp;t_ini, NULL);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;/* ...hacer algo... */&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;gettimeofday(&amp;amp;t_fin, NULL);&lt;br /&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;secs = timeval_diff(&amp;amp;t_fin, &amp;amp;t_ini);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;printf(&quot;%.16g milliseconds&amp;#92;n&quot;, secs * 1000.0);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Como puede ver la estructura &lt;em&gt;timeval&lt;/em&gt; contiene dos campos, segundos y microsegundos transcurridos (tv_sec y tv_usec respectivamente), por lo tanto ofrece una precisión de microsegundos. De todas formas, como decía esto en Windows no sirve y la razón es sencilla, en la misma &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://msdn2.microsoft.com/en-us/library/ms725496%28VS.85%29.aspx&quot;&gt;MSDN&lt;/a&gt; explican que el temporizador del sistema corre aproximadamente a unos 10 milisegundos, por lo tanto, cualquier función que lo utilice nos estará dando la misma asquerosa precisión (inclusive al utilizar &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com.ar/search?q=GetSystemTimeAsFileTime+msdn&quot;&gt;GetSystemTimeAsFileTime&lt;/a&gt; y &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com.ar/search?q=FILETIME+msdn&quot;&gt;FILETIME&lt;/a&gt;). Por lo tanto la solución es utilizar lo que se conoce en el mundo de Windows como el &quot;contador de rendimiento de alta resolución&quot; (&lt;em&gt;high-resolution performance counter&lt;/em&gt;):&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;windows.h&amp;gt;&lt;br /&gt;&lt;br /&gt;/* retorna &quot;a - b&quot; en segundos */&lt;br /&gt;double performancecounter_diff(LARGE_INTEGER *a, LARGE_INTEGER *b)&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;LARGE_INTEGER freq;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;QueryPerformanceFrequency(&amp;amp;freq);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;return (double)(a-&amp;gt;QuadPart - b-&amp;gt;QuadPart) / (double)freq.QuadPart;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;LARGE_INTEGER t_ini, t_fin;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;double secs;&lt;br /&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;QueryPerformanceCounter(&amp;amp;t_ini);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;/* ...hacer algo... */&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;QueryPerformanceCounter(&amp;amp;t_fin);&lt;br /&gt;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;secs = performancecounter_diff(&amp;amp;t_fin, &amp;amp;t_ini);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;printf(&quot;%.16g milliseconds&amp;#92;n&quot;, secs * 1000.0);&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;return 0;&lt;br /&gt;}&lt;/pre&gt;En este caso, imagine que &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com.ar/search?q=QueryPerformanceCounter+msdn&quot;&gt;QueryPerformanceCounter&lt;/a&gt; es como &lt;em&gt;clock()&lt;/em&gt; y &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com.ar/search?q=QueryPerformanceFrequency+msdn&quot;&gt;QueryPerformanceFrequency&lt;/a&gt; es como CLOCKS_PER_SEC. Es decir, la primera función nos da el valor del contador, y la segunda su frecuencia (en ciclos por segundo, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Hertz&quot;&gt;hertz&lt;/a&gt;). Cabe aclarar que un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com.ar/search?q=LARGE_INTEGER+msdn&quot;&gt;LARGE_INTEGER&lt;/a&gt; es una forma de representar un entero de 64 bits por medio de una unión (&lt;em&gt;union&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;Como tarea al lector, si es que existe alguno, le queda hacer una versión &quot;portable&quot; (entre Windows y Linux) para medir el rendimiento (con unos cuantos &lt;em&gt;#ifdef WIN32&lt;/em&gt; y &lt;em&gt;#endif&lt;/em&gt; sería suficiente).&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;18 de Marzo del 2008&lt;/span&gt;: acá transcribo una macro que me pasó el amigo &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.carlosbecker.com.ar/&quot;&gt;Carlos Becker&lt;/a&gt; para medir el tiempo de una rutina en Linux mediante &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.tin.org/bin/man.cgi?section=3&amp;topic=clock_gettime&quot;&gt;clock_gettime&lt;/a&gt;:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#define TIME_THIS(X) &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;{ &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;struct timespec ts1, ts2; &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;clock_gettime( CLOCK_REALTIME, &amp;amp;ts1 ); &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;X; &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;clock_gettime( CLOCK_REALTIME, &amp;amp;ts2 ); &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;printf( #X &quot; demora: %f&amp;#92;n&quot;, &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;(float) ( 1.0*(1.0*ts2.tv_nsec - ts1.tv_nsec*1.0)*1e-9 &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;+ 1.0*ts2.tv_sec - 1.0*ts1.tv_sec ) ); &amp;#92;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;}&lt;br /&gt;&lt;br /&gt;/* podemos usarla así */&lt;br /&gt;{&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;double x, y, z;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;x = 2.0;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;y = 4.0;&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;TIME_THIS(z = sqrt(x*x + y*y));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Lo que da como resultado:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;z = sqrt(x*x + y*y) demora: 0.015164&lt;br /&gt;&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-2720258185855146665?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-2720258185855146665</guid>
         <pubDate>Sat, 01 Mar 2008 03:59:00 -0800</pubDate>
      </item>
      <item>
         <title>Conseguir un compilador</title>
         <link>http://cmasomenos.blogspot.com/2008/02/conseguir-un-compilador.html</link>
         <description>En este blog vamos a hablar sobre los lenguajes de programación C y C++, y cómo usar software GNU para hacer aplicaciones. También voy a tratar de investigar algo de ensamblador.&lt;br /&gt;&lt;br /&gt;De todas formas, para evitar hacer un primer post completamente inútil &quot;de presentación&quot;, voy a pasar a explicarles cómo pueden instalar un compilador gratuito en Windows desde cero, y hacer un pequeño programa &lt;span style=&quot;font-style:italic;&quot;&gt;&quot;Hola Mundo&quot;&lt;/span&gt; sin pensar mucho (eso sí, van a tener que leer un poco). El proceso para Linux es más sencillo, ya que el compilador suele venir instalado por defecto en la mayoría de las distribuciones.&lt;br /&gt;&lt;br /&gt;Primero, algunas definiciones importantes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.mingw.org/&quot; style=&quot;font-weight:bold;&quot;&gt;MinGW&lt;/a&gt;: Un conjunto de programas y bibliotecas que permiten crear aplicaciones para Windows.&lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gcc.gnu.org/&quot; style=&quot;font-weight:bold;&quot;&gt;GCC&lt;/a&gt;: El compilador. Transforma código escrito en C/C++ a un archivo ejecutable (.exe). En realidad hace miles de maravillas más, pero por ahora nos vamos a quedar con esta definición.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;MSYS&lt;/span&gt;: Es un conjunto mínimo de programas para poder ejecutar scripts &lt;span style=&quot;font-style:italic;&quot;&gt;&quot;a la&quot;&lt;/span&gt; Unix. Además incluye una terminal que emula un pequeño entorno GNU/Linux.&lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.gnu.org/software/emacs/&quot; style=&quot;font-weight:bold;&quot;&gt;Emacs&lt;/a&gt;: La madre de los editores de texto. Alguna vez dije que era una porquería o muy complicado, y que conviene usar editores como el &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://sourceforge.net/projects/rhide&quot;&gt;RHIDE&lt;/a&gt; o &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://setedit.sourceforge.net/&quot;&gt;Setedit&lt;/a&gt;. Bueno, la cosa es que con &quot;&lt;span style=&quot;font-style:italic;&quot;&gt;un poco&lt;/span&gt;&quot; de práctica uno comprende el poder de esta herramienta.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;make&lt;/span&gt;: Un programa que puede compilar muchos archivos y linkearlos en un ejecutable de forma automatizada (siempre y cuando le escribamos un archivo con las órdenes adecuadas). Generalmente los programadores están acostumbrados a utilizar un &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://es.wikipedia.org/wiki/Entorno_de_desarrollo_integrado&quot;&gt;IDE&lt;/a&gt; (como el &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.bloodshed.net/devcpp.html&quot;&gt;DevC++&lt;/a&gt;) que maneje el proyecto, calcule las dependencias entre archivos, compile todo lo necesario, linkee, ejecute y depure. Si bien esto es cómodo, espero poder enseñarles a automatizar la compilación y liberarlos de un determinado IDE para compilar los programas.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;cmd.exe&lt;/span&gt;: Es la línea de comandos de Windows. Si nunca lo utilizó, es hora que se ponga a usarlo. Para iniciar la línea de comandos debe ir al menú &quot;Inicio/Ejecutar...&quot; e introducir &quot;cmd&quot;. ¿Cómo se usa? Bueno, &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.google.com.ar/search?q=introduccion+al+shell+de+comandos+cmd.exe&quot;&gt;empiece a buscar...&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Ahora nos dedicaremos a instalar el MinGW, para eso debe comenzar a bajarse los siguientes archivos (si no sabe &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.7-zip.org/&quot;&gt;cómo descomprimir un archivo .tar.gz...&lt;/a&gt;):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://downloads.sourceforge.net/mingw/mingw-runtime-3.13.tar.gz?download&quot;&gt;mingw-runtime-3.13.tar.gz&lt;/a&gt;: Los archivos de cabecera y bibliotecas estándares (stdio.h, math.h, libc, libm, etc.) &lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://downloads.sourceforge.net/mingw/w32api-3.10.tar.gz?download&quot;&gt;w32api-3.10.tar.gz&lt;/a&gt;: Archivos de cabecera del API de Win32&lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://downloads.sourceforge.net/mingw/gcc-core-3.4.5-20060117-1.tar.gz?download&quot;&gt;gcc-core-3.4.5-20060117-1.tar.gz&lt;/a&gt;: El preprocesador de C y el compilador de C&lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://downloads.sourceforge.net/mingw/gcc-g++-3.4.5-20060117-1.tar.gz?download&quot;&gt;gcc-g++-3.4.5-20060117-1.tar.gz&lt;/a&gt;: El compilador de C++ y los archivos de cabecera de C++&lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://downloads.sourceforge.net/mingw/binutils-2.17.50-20060824-1.tar.gz?download&quot;&gt;binutils-2.17.50-20060824-1.tar.gz&lt;/a&gt;: Varios programas utilitarios que sirve para diferentes propósitos (ej: quitar símbolos de depuración con &lt;span style=&quot;font-style:italic;&quot;&gt;strip&lt;/span&gt;, convertir direcciones a líneas de código fuente con &lt;span style=&quot;font-style:italic;&quot;&gt;addr2line&lt;/span&gt;, procesar la información de &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://en.wikipedia.org/wiki/Performance_analysis&quot;&gt;rendimiento&lt;/a&gt; con &lt;span style=&quot;font-style:italic;&quot;&gt;gprof&lt;/span&gt;, crear librerías con &lt;span style=&quot;font-style:italic;&quot;&gt;ar&lt;/span&gt;, compilar los archivos de recursos de Windows con &lt;span style=&quot;font-style:italic;&quot;&gt;windres&lt;/span&gt;, etc.).&lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://downloads.sourceforge.net/mingw/mingw32-make-3.81-2.tar.gz?download&quot;&gt;mingw32-make-3.81-2.tar.gz&lt;/a&gt;: La utilidad &lt;span style=&quot;font-style:italic;&quot;&gt;make&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://downloads.sourceforge.net/mingw/gdb-5.2.1-1.exe?download&quot;&gt;gdb-5.2.1-1.exe&lt;/a&gt;: El depurador de código&lt;/li&gt;&lt;/ul&gt;Una vez que consiga todos estos archivos, debe crear una carpeta C:&amp;#92;MinGW (le recomiendo esa ubicación) y descomprimir todo ahí mismo. Para instalar el depurador (gdb) deberá ejecutar el instalador, seguir los pasos, y colocar como carpeta de instalación &quot;C:&amp;#92;MinGW&quot;.&lt;br /&gt;&lt;br /&gt;Una vez instalado todo, usted ya está en condiciones para compilar código en C o C++. Antes verifique que en dicha carpeta tiene una estructura de directorios como la siguiente:&lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;C:&amp;#92;MinGW&lt;br /&gt; bin&amp;#92;&lt;br /&gt; doc&amp;#92;&lt;br /&gt; include&amp;#92;&lt;br /&gt; info&amp;#92;&lt;br /&gt; lib&amp;#92;&lt;br /&gt; libexec&amp;#92;&lt;br /&gt; man&amp;#92;&lt;br /&gt; mingw32&amp;#92;&lt;br /&gt;&lt;/pre&gt;Si así es, significa que todo salió bien (bueno, tampoco descomprimir unos archivos es algo tan complicado).&lt;br /&gt;&lt;br /&gt;Para estar seguros que el compilador funcione, vamos a crear el programa de prueba por excelencia, el &quot;Hola Mundo&quot;. Abra el bloc de notas (Inicio/Ejecutar/notepad) y escriba en un archivo el siguiente código:&lt;br /&gt;&lt;pre class=&quot;prettyprint&quot;&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt; printf(&quot;Hola Mundo&amp;#92;n&quot;);&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Guarde el archivo como &quot;&lt;span style=&quot;font-style:italic;&quot;&gt;C:&amp;#92;MinGW&amp;#92;hola.c&lt;/span&gt;&quot;. Ahora abra la línea de comandos &lt;span style=&quot;font-weight:bold;&quot;&gt;cmd.exe&lt;/span&gt;, y ahí mismo ejecute los siguientes comandos:&lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;cd C:&amp;#92;MinGW&lt;br /&gt;set PATH=C:&amp;#92;MinGW&amp;#92;bin;%PATH%&lt;br /&gt;gcc hola.c&lt;br /&gt;&lt;/pre&gt;Verá que el archivo &quot;&lt;span style=&quot;font-style:italic;&quot;&gt;a.exe&lt;/span&gt;&quot; se crea en el directorio C:&amp;#92;MinGW. Si ejecuta el programa &lt;span style=&quot;font-weight:bold;&quot;&gt;a.exe&lt;/span&gt; visualizará en la salida de la consola el mensaje más estúpido jamás escrito: &quot;&lt;span style=&quot;font-style:italic;&quot;&gt;Hola Mundo&lt;/span&gt;&quot;&lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;C:&amp;#92;MinGW&amp;gt;a.exe&lt;br /&gt;Hola Mundo&lt;br /&gt;&lt;/pre&gt;A continuación le paso a explicar qué hicimos en esta ráfaga de pasos:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&quot;cd C:&amp;#92;MinGW&quot; es para ubicarnos en el directorio donde se encuentra el archivo o proyecto que queremos compilar (si no sabía esto, es porque todavía no estuvo buscando cómo usar cmd.exe...).&lt;/li&gt;&lt;li&gt;&quot;set PATH=C:&amp;#92;MinGW&amp;#92;bin;%PATH%&quot; es un conjunto de varias cosas: &quot;&lt;span style=&quot;font-style:italic;&quot;&gt;PATH&lt;/span&gt;&quot; es una variable de entorno que indica cuáles son los directorios donde podemos encontrar archivos ejecutables (archivos ejecutables como &lt;span style=&quot;font-style:italic;&quot;&gt;gcc.exe&lt;/span&gt;, &lt;span style=&quot;font-style:italic;&quot;&gt;cpp.exe&lt;/span&gt;, etc.); &quot;&lt;span style=&quot;font-style:italic;&quot;&gt;set&lt;/span&gt;&quot; es un comando del shell para cambiar el valor de una variable de entorno; y &quot;&lt;span style=&quot;font-style:italic;&quot;&gt;%PATH%&lt;/span&gt;&quot; devuelve el valor de dicha variable de entorno. Por lo tanto, lo único que estamos haciendo aquí es agregar una nueva ruta (C:&amp;#92;MinGW&amp;#92;bin) a PATH para que el shell encuentre los archivos ejecutables que a nosotros nos interesa (el preprocesador, compilador, etc.). Si desea ver dónde busca el shell los archivos ejecutables actualmente, puede usar el siguiente comando: &quot;&lt;span style=&quot;font-style:italic;&quot;&gt;echo %PATH%&lt;/span&gt;&quot;&lt;/li&gt;&lt;li&gt;&quot;gcc hola.c&quot; compila el programa &quot;hola.c&quot; y deja el resultado (&lt;span style=&quot;font-style:italic;&quot;&gt;linkea&lt;/span&gt; o &lt;span style=&quot;font-style:italic;&quot;&gt;linkedita&lt;/span&gt;) en un archivo llamado &quot;a.exe&quot; (o &quot;a.out&quot; en Linux). En otros posts veremos cómo podemos especificar un nombre distinto a este archivo de salida.&lt;/li&gt;&lt;/ul&gt;De todo lo visto, lo más molesto es la configuración de la variable de entorno, es decir, si pensamos compilar varias veces, cada vez que abramos un shell (cmd.exe) deberemos hacer un &quot;set PATH=C:&amp;#92;MinGW&amp;#92;bin;%PATH%&quot;. Para evitar este paso tenemos dos opciones:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Si tiene accesos de Administrador, puede hacer click derecho sobre &quot;Mi PC&quot;, &quot;Propiedades&quot;, &quot;Opciones Avanzadas&quot;, &quot;Variables de Entorno&quot; y modificar la variable PATH agregándole el valor &quot;C:&amp;#92;MinGW&amp;#92;bin&quot; (recuerde no tocar las demás rutas, además de agregar un &quot;;&quot; para separar las distintas rutas entre sí).&lt;/li&gt;&lt;li&gt;En otro caso, puede crearse un archivo de comandos por lotes mi-mingw.bat para iniciar el shell adecuadamente con el PATH ya configurado. Por ejemplo, un mi-mingw.bat posible podría ser:&lt;br /&gt;&lt;pre class=&quot;console&quot;&gt;set PATH=C:&amp;#92;MinGW&amp;#92;bin;%PATH%&lt;br /&gt;start cmd.exe&lt;br /&gt;&lt;/pre&gt;Este archivo podemos dejarlo en el Escritorio y cada vez que tengamos ganas de compilar, con un simple doble click ya podemos empezar. Inclusive, en vez de iniciar &quot;start cmd.exe&quot; podríamos iniciar algún IDE o editor de texto como Emacs. Pero eso para otro post.&lt;/li&gt;&lt;/ol&gt;Bueno, por hoy me cansé. Cualquier problema o pregunta que tengan, los comentarios están abiertos (y bien moderados :)&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4295741868585735005-6099656894518733137?l=cmasomenos.blogspot.com' alt=''/&gt;&lt;/div&gt;</description>
         <author>David Capello</author>
         <guid isPermaLink="false">tag:blogger.com,1999:blog-4295741868585735005.post-6099656894518733137</guid>
         <pubDate>Sun, 17 Feb 2008 08:55:00 -0800</pubDate>
      </item>
   </channel>
</rss>
<!-- fe6.pipes.re3.yahoo.com uncompressed/chunked Thu Jul 29 14:34:04 PDT 2010 -->
