C Programming in Windows

Making "Hello, World!" Easy


Update: can go to your project, Properties, Linker, SubSystem, change from Windows to Console and can just use main().

Programming in the language C isn’t immediatly the same or as easy in Windows as it is on Linux or Macs. This is a guide to setup your C development environment on Windows similar to those other operating systems. I learned this from following the Handmade Hero project.

Your first program in any language is usually “Hello, World!” Here is the classic program in C that would be in a single file called something like helloworld.c.

#include <stdio.h>

main() {
    printf("Hello, World!\n");

Rather small. Heck, we can shorten this to two lines.

Now let’s say you want to start programming in C. In Linux or on a Mac, you can just make this one file and compile in the command line and you’re done.

But you probably use Windows. That means you’ll use Windows’ developer tools Visual Studio. They make this freely available in their Community edition. You should install this, but what I’m describing next you don’t have to do, I’m just showing what I’d do as a beginner that didn’t know better.

So you’d install that and start it up. You start a new project in Visual C++, and it will be just a simple one in the console so you select Win32 Console Application. Visual Studio will create an entire solution for you with several files and directories unlike the single file the typical C tutorial might start you with.

And the code you start out with looks a little different.

// HelloWorld.cpp : Defines the entry point for the console application.

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
    return 0;

You can put a printf("Hello, World!\n"); before the return statement, but this still looks different than what you were probably told and for all you know it can only be built in Visual Studios. How can you go to just one file compiled at the command line with that same code in Windows but without having to write the code in Visual Studio?

You might get told to use MinGW or Cygwin, but those are additional tools and I prefer to have less and not more tools to worry about.

When you install Visual Studio, you also get command line tools to compile your code without opening Visual Studio. These are located at a directory like

C:\Program Files (x86)\Microsoft Visual Studio Community 2013

I have some older versions, like 11.0, but that’s for I think Visual Studio 2010. Just be mindful the version might not be the same as the branding name which is usually the year.

To compile from the command line, you need to set some environment variables. In the Visual Studio directory, there should be a directory named “VC” for Visual C++ that will have the files you need. There is a batch file named vcvarsall.bat that will setup all the environment variables for you. Run that in your command line window.

"C:\Program Files (x86)\Microsoft Visual Studio Community 2013\VC\vcvarsall.bat"

This will setup the environment variables for that command line session only. You can now type “cl” to run the compiler. If you open another command line window, it won’t work since that new window doesn’t have the environment variables setup for it.

This will compile for 32 bit programs. To compile for 64 bit, add the option at the end.

"C:\Program Files (x86)\Microsoft Visual Studio Community 2013\VC\vcvarsall.bat" x64

This is annoying to type each time, so this can be placed in a batch file. Create a new file named “shell.bat”. Make sure the file name really is named only “shell.bat” with the .bat as the extension. I recall Windows may hide the file extension and you may rename “New Text Document.txt” to “shell.bat.txt” if you can’t see the file extension.

Now put the call to the vcvarsall batch file in your new batch file.

@echo off
REM any line in a batch files starting with REM is a comment and will be ignored
REM the @echo off is to suppress printing output of commands in the batch file
call "C:\Program Files (x86)\Microsoft Visual Studio Community 2013\VC\vcvarsall.bat" x64

call is used in batch files to call other batch files and immediately return. I don’t think it’s required but I think a good thing to do.

But you still need to type the path to that batch file. Let’s turn it into a shortcut. Right click where you want the shortcut like on the desktop, select New->Shortcut. Enter this for the location of the target:

%windir%\system32\cmd.exe /k c:\path\to\your\shell.bat

Can also find the command prompt in the Start menu, drag with the right mouse button to say the desktop to create the shortcut, then right click it and edit it there.

then name and create the shortcut. Now right click the shortcut, properties, and have it start in where ever you want to compile at. You can now just double-click the shortcut to bring up a command line window with the environment variables setup.

You may be able to have the shortcut point directly to vcvarsall.bat, but having your own shell.bat may be helpful if you want to change the compiler version or have other startup commands run.

With your helloworld.c file with the classic program, you can now compile it with

cl helloworld.c

This will create the executable helloworld.exe that you can run with simply


I tend to add -FC for more verbose output but it never seems to do much. To include debugging information, add the compiler option -Zi. Or /Zi.

cl -FC -Zi helloworld.c

You can make this easier by putting this in a batch file also. In misc\build.bat

@echo off
mkdir ..\build
pushd ..\build
cl -Zi ..\code\win32_handmade.cpp user32.lib

user32.lib is the import library you need for UI type stuff like windows or message boxes. If not included, you’ll get unresolved external symbol error in linker.

This has some extra stuff for Handmade Hero. The project directory has a separate code and build directory. This creates the build directory if not already there, goes into the build directory, builds the code in the code directory, goes back to the directory it was previously in before the build directory.

Also in the misc directory, you can put an Emacs batch file to start Emacs in your development directory with your .emacs config file. Make the file misc\emacs.bat with

@echo off
"C:\path\to\emacs\bin\runemacs.exe" -q -l w:\projectpath\misc\.emacs

This will run emacs, quiet any startup messages, and load your .emacs file.

You’ll still need Visual Studio as a debugger, which does a really good job. To start debugging your command line program, run

devenv helloworld.exe

To have it break at main type F11. Then you can step through instructions with F10, step into other functions with F11, place breakpoints at the line with the cursor with F9, run until you hit a breakpoint with F5, and stop debugging with Shift-F5.

To look at contents of variables, go to Debug, Windows, Watch, and choose one of the watch windows. You can then type in the name of the variable or a simple expression to see it’s value.

You could make a new virtual drive letter for your code directory. This is good for organization, and all the path names in you code could be w:\my_code instead of using relative paths. To associate a path with a virtual drive letter:

subst w: C:\Users\faehnrich\Documents\code

This will make a drive w that points directly to that path. You can create this virtual drive at startup by putting it in a batch file in your Startup directory. Create a file named something like startup.bat at C:\Users\myusername\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup (replacing eric with your user name.) In it, put

@echo off
subst w: C:\Users\faehnrich\Documents\code

To get rid of the virtual drive letter,

subst w: /d

You may also want to set the PATH variable to include the path to your batch files. Set the path with

set path=w:\projectpath\misc;%path%

To see the full all environment variables you just type set?

This will add your misc directory to the beginning of the path variable. I put this in the startup batch file, but don’t think it works and only worked in the shell batch file.

Having the path to your batch files means starting up your shell, you can just type build to build or emacs to start emacs.