Category: C

Undefined behaviour in C

Undefined behaviour in C

Unexpected
Image by John Hain from Pixabay

One of C’s not so brilliant features is the range of Undefined Behaviour (UB). Things like using an uninitialised variable or having an int variable overflow don’t have behaviour defined; thus it is UB and you cannot accurately predict what will happen. Likewise accessing a NULL pointer can cause odd behaviour. It gets more sophisticated than that. What if you type cast an int to a float?

The LLVM blog have an interesting set of posts on UB and it’s definitely worth reading. I’ve done a lot of C programming, so I’m rarely surprised by my programs but its useful to know about these things. In my case, I started with assembler programming and then learnt C++ and C in that order so my perspective has always been to try and understand whats going on deep down.

Chess in C

Chess in C

Tom Kerrigan ChessI noticed that the Covid lockdown had made streaming of chess games very popular and did a search to see if I could find the source of one in C. The first one I found was actually C++ (cout << is a bit of a giveaway!) but I found this one by a developer called Tom Kerrigan. It runs from the command line and the exe is just 157 KB in size.

Note it is copyrighted but he has put his source code out there so if you are interested in seeing how a chess program is written this is an excellent place to start. His code also includes a lot of comments and includes an opening book.

 

Modern C – a Free Ebook

Modern C – a Free Ebook

Modern C by Jens GustedtThis is the 2nd edition. Author Jens Gustedt has generously allowed a free version to be downloaded from his website.

If you like his book which is also published by Manning then you should consider buying a copy. He provides a 35% discount for the print or E book version.

I scanned the E-book and must admit, the bit on  signal handling taught me a lot that I didn’t know.

The E-book is nearly 300 pages long in 19 chapters.

Interesting C Program- What do you think it does?

Interesting C Program- What do you think it does?

Question mark
Image by Gordon Johnson from Pixabay

This is a past IOCCC winner. It needs a #include <stdio.h> to compile.

#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}

When I compiled and ran it in Visual Studio it output 0.25 which is not the value it’s intended to output. That said it also messed up the formatting.

I can’t recommend this formatting BTW but then that’s the idea, to obfuscate i.e. disguise its purpose! So have you figured it out yet? I put the image on the right so as not to break up the program listing…

How to calculate how effective a Riffle is

How to calculate how effective a Riffle is

deck of cards
Image by Hebi B. from Pixabay

In my previous post I mentioned about writing a program to determine how effective a riffle shuffle was. So here’s the code.

How it works

I’m using an array of 52 chars to hold the deck. I’m only interested in the card’s position in the deck so each card is initialised with a value in the range 0-51. I’m using three other similar sized arrays.

  • tempCards are used purely for doing the riffle.
  • distances are used to calculate the maximum distance the card moved
  • startPos tracks the cards starting position 0-51 before doing lots of rounds of riffles.

The program starts by picking up ( as a parameter) how many rounds you want it to run. It defaults to 10 if no value is input.

It then clears distances and inits cards. In each round, it starts by storing card positions in startPos. It then does seven riffles and works out how far a card has moved. If it has moved more than before (in distances) it stores it in distances.

DoRiffle works by indexing through the two 1/2 deck piles taking a card from each and a 50:50 random chance determines which of the two cards goes into the shuffled deck first and then second.

Here’s the listing.

// riffle.c by D. Bolton (C) 2020 Learncgames.com - TYou are free to redistribute but please keep this line in

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// #defines
#define MAXROUNDS 10
#define NUMRIFFLES 7
#define NUMCARDS 52

// variables
int NumRounds;
char cards[NUMCARDS],tempCards[NUMCARDS],startPos[NUMCARDS];
int distances[NUMCARDS];
time_t t;

// functions

// Convert string to int calling strtol
int GetIntArg(char* str) {
	char* ptr;
	return strtol(str, &ptr, 10);
}

// Merges two cards a and b. 50:50 chance that a above b or other way
void DoRiffle() {
	// Copy cards into tempCards
	memcpy(tempCards, cards, sizeof(cards));
	// Merge each pair of cards tempCards[i] and TempCards[i+26]
	int cardIndex = 0;
	for (int i = 0; i < NUMCARDS / 2; i++) {
		if (rand() % 2) {
			cards[cardIndex++] = tempCards[i];
			cards[cardIndex++] = tempCards[i + 26];

		}
		else {
			cards[cardIndex++] = tempCards[i + 26];
			cards[cardIndex++] = tempCards[i];
		}
	}
}

// Works out how far cards have moved, added to distances
void CalculateDistances() {
	for (int i = 0; i < NUMCARDS; i++) {
		int moved = abs(cards[i] - startPos[i]);
		if (moved > distances[i])
			distances[i] = moved;
	}
}

void DoShuffles() {
	// Clear distances and init cards
	for (char i = 0; i < NUMCARDS; i++) {
		distances[i] = 0;		
		cards[i] = i;
	}
    // do Numrounds  rounds
	for (int round =0;round<NumRounds;round++){
		// Mark where the card starts
		for (char i = 0; i < NUMCARDS; i++) {
			startPos[i] = cards[i];
		}
		// Do seven riffles
		for (int i = 0; i < NUMRIFFLES; i++) {
			DoRiffle();
		}		
		CalculateDistances();
	}
	int furthest = 0;
	for (int i = 0; i < NUMCARDS; i++) {
		printf("Distance[%d]=%d\n", i, distances[i]);
		if (distances[i]> furthest) {
			furthest = distances[i];
		}
	}
	printf("furthest moved is %d\n", furthest);
}


int main(int argc, char* argv[]) {
	srand((unsigned)time(&t));
	if (argc ==1 || argc== 2) {
		NumRounds = MAXROUNDS;
		if (argc == 2) {
			NumRounds = GetIntArg(argv[1]);
			printf("Numrounds = %d\n", NumRounds);
		}
		DoShuffles();
	}
	else {
		printf("Please supply 0 or 1 arguments e.g. riffle 60\n");
	}
}

Even with ten rounds I’ve seen cards move 51 positions. With 5,000 rounds all cards but one moved by 51 and one by 50.

How to install SDL2 in Visual Studio

How to install SDL2 in Visual Studio

Visual Studio IDEThis is the first of a number of longer-piece game related tutorials. You’ll see I’ve added a tutorials link to the top menu. That page will grow as I add tutorials, as each is added to it .

You’ll see I use the terms SDL and SDL2 mostly interchangeably. SDL is the name of the library but we don’t want the older SDL1 instead we want SDL2 which seems more or less permanently at version 2.0.12.

I’ve left the Visual Studio version off as the process is mostly the same whether it’s Visual Studio 2017, 2019 or future versions. Screenshots are from Visual Studio 2019.

You don’t have to do this on Linux as it takes three or four sudo apt installs to add the various SDL2 dev modules in, but with Windows you need to configure Visual Studio and it can be a somewhat confusing process if you are new to Visual Studio.

Also you need to download and fetch the various files. This is made slightly more complicated because there are 32-bit and 64-bit versions and you want to keep them both so you can switch between the two.

Here are the various steps we have to go through.

  1. Download the various files and unzip them
  2. Setup include and lib paths in Visual Studio
  3. Add the lib files into Visual Studio.
  4. Copy the dlls into the folder where the game will run.
  5. Compile and run it.

What you are downloading are basically three types of files.

  1. Header files., This is files like sdl.h.  Your program will #include these.
  2. Lib files. This is the bulk of the SDL code.
  3. Dll files (Dynamic Link Liobraries). Needed for runtime.

Download the various files and unzip them

The SDL website is libsdl.org and if you click the SDL Releases in the bottom right it will take you to the SDL downloads page. WE don’t need the source code (you are welcome to download it and take a look but it’s not needed to use SDL2.

We do however need the development libraries. These include the runtime binaries so we don’t need to download those. as well. Just the one file SDL2-devel-2.0.12-VC.zip

I suggest you create a folder SDL or SDL2 on your drive. My C: drive is for Windows so I use d: \SDL2

If you unzip the files into there you’ll end up with three folders and five .txt files. Just under 7 MB in total. Other than docs there are include and lib.  The lib folder is further split into x64 (64-bit) and x86 (32-bit) . It also includes the runtime dlls. These will have to be in the path for your program but we’ll leave that until later.

Sounds, Images and Truetype fonts

As well as these, you are probably going to want image file support, sounds and possibly truetype font support in your program. These are separate files in the SDL projects folder.

  1. Image file support. Download the development library file from the sdl_image page. As before you want development library file. SDL2_image-devel-2.0.5-VC.zip.
  2. Sounds file support. Download the development library from the sdl mixer page. It’s SDL2_mixer-devel-2.0.4-VC.zip.
  3. ttf file support. Once again a development library downloaded from the SDL_ttf project page. It’s SDL2_ttf-devel-2.0.15-VC.zip.

All three files have similar structure to the SDL2 dev library.  Unzip the include files into the SDL include folder and the lib files into the relevant X86 and X64 lib sub-folders. So all your SDL files that you need are in the same include and lib sub-folders.

I suggest you extract the file folders one by one, do the three include files first then the x64 files and then the x86. Do not get x86 and x64 mixed up. The only way to tell them apart is by size and it’s not always an accurate way.  Don’t worry if it complains about overwriting zlib1.dll. There’s a copy in both the images and sounds zip files.

Setup include and lib paths in Visual Studio

This can be a bit complicated, just follow these instructions exactly.

To configure a C/C++ project in Visual Studio, you have to specify where the compiler gets its include files, where it finds its lib files and which lib files you want to link to.

Solution ExplorerI’ve created a blank C++ project called sdltest in VS 2019.  Now I actually want it to be a C project so just rename the main file sdltest.cpp to sdltest.c. You need to delete all of the C++ code in that file as well.  After renaming the Solution Explorer should look something like this. We will have a sdltest program to run later so just save this for now. You can get the file from GitHub and overwrite sdltest.c.

Now click Project on the top menu then sdltest properties at the foot of the menu.  You should see this form (below).  This is how you specify properties for your project in Visual Studio.

You’ll see I have selected VC++ Directories on the left. This is where you specify some of the directories (folders and directories mean the same thing BTW) .

But the Platforms pull down probably shows Win32 on yours. Change it to All Platforms. Visual Studio lets you specify configurations for all things or for x86 or x64 separately. We’ll use the same include folders for both x86 and x64 but we’ll specify the paths to the lib files individually as the x64 lib files are in the x64 sub-folder and the x86 files in the x86 folder.

Property Pages
To specify the path click on Include Directories, you’ll see a down arrow appear on the right.  Click it and you’ll see <Edit…> appear, click it and a form like this below will popup.
Visual studio folder editClick on the blue area in the form and you’ll be able to paste or type in the path or click the … button to get a file browser appear. Type in, paste or select the folder then press Ok.  You should now see your path in the folders.

Here I typed in d:\SDL\Include. Be careful that you don’t get rid of $(VC_includePath);$(WindowsSDK_IncludePath); in the include path as I did as your program won’t compile!

folder paths

We now have to do the same for the lib paths.  But first we must change the Platform to specify x86 or x64.

If you change it, a popup will appear asking if you want to save your changes. Click the Yes button.

Confusingly the platform choices on mine are Win32 and x64, but Win32 is the same as x86.

You’ll see that the include path you added shows up in the x86/Win32 platforms because we changed it for all platforms.

Now add the path for Library Directories. Click the down arrow then <edit…> and put in the full path to the folder that matches the Platform. x86 for Win32 platform, x64 for x64 platform. After you’ve entered it will show up in the directories.

Visual studio all paths

If you want both x64 and x86 then change the platform and re-enter it. Don’t forget to save!

Add the lib files into Visual Studio

The last configuration to do is specify the lib files that are needed. We’ve specified the paths for include and lib files but the compiler linker doesn’t know what lib files to link.

As linking depends on 32-bit or 64-bit we have to specify this twice as we did for the lib paths. It’s in a different place in the property pages. Click Linker then Input.

Visual Studio Linker Configuration It’s the top line (Additional Dependencies) that we need to work with. Click into it to get the down arrow then click that and the <edit…> as before.

You’ll have noticed that it comes pre-populated with all the various library .lib files.  We’ll be adding some more. The ones we need are

SDl2.lib SDL2_mixer.lib SDL2_ttf.lib SDL2_image.lib and SDL2main.lib

Add these into the edit box one by one and press return after each one.

After you’ve added them and pressed Ok, you’ll see them in a list. Something like this though I’ve not added SDL2_ttf.lib in to it yet.

As before repeat for both x86 and x64.

 

We’re now ready to compile. Only we need a program to do that. I’m not going to list the whole sdltest as it’s 135 lines but you can download the VS project in the file sdltest.zip from GitHub. It should compile with no errors. If you get errors, please recheck the include folders and lib folders and make sure you have configured them correctly.

So it compiles, but it won’t run. If you look in the Debug folder under the x64 (or Win32 if you built that) , you’ll see a whole lot of files. but only sdltest.exe is important. You can delete the rest. Leave sdltest.pdb if you wish to debug.

We have to

Copy the dlls into the folder where the game will run

That folder is this the \sdltest\x64\Debug folder. We need several .dll files from the same lib folder that holds the x64 libs. (Again if you are on Win32 you need dlls from the x86 lib folder).

What files do we need?

Just SDL2.dll. If we were using images we’d also need sdl2_image.dll and zlib1.dll. We don’t currently need the SDL2_mixer.dll or the SDL2_ttf.dll but if you ever use sounds or Truetype then you’ll need those. For sounds you’ll also need some of the lib*.dll files such as libogg-0.dll or libvorbis-0.dll. For image we might need in the future libjpeg-9.dll (if we ever use jpg files).

So you’ve compiled it and should see something like this when you run sdltest.exe. It doesn’t do much except draw coloured rectangles. Press the esc key to close it. On my POC it draws 100,000 coloured rectangles each 120 x 120 pixels in about a second. That’s pretty fast!

The heart of the program is this function:

void DrawRandomRectangle() {
	char buff[20];
	SDL_Rect rect;
	SDL_SetRenderDrawColor(renderer, Random(256) - 1, Random(256) - 1, Random(256) - 1, 255);
	rect.h = 120;// Random(100) + 20;
	rect.w = 120;// Random(100) + 20;
	rect.y = Random(HEIGHT - rect.h - 1);
	rect.x = Random(WIDTH - rect.w - 1);
	SDL_RenderFillRect(renderer, &rect);

	rectCount++;
	if (rectCount % 100000 == 0) {
		SDL_RenderPresent(renderer);
		stopTimer(&s);
		sprintf_s(buff, sizeof(buff), "%10.6f", getElapsedTime(&s));
		SetCaption(buff);
		startTimer(&s);
	}
}

Uncomment the two lines with 120; // Random(100) + 20; to have it draw random sized rectangles. The figure in the caption is how long it takes to draw 100,000 rectangles.

A graphics editor in C

A graphics editor in C

Screenshot of grafX2 As the picture shows, no one has ever accused me of being artistic! Hey I can’t be good at everything (sometimes it feels like anything but it passes!) and I’ve long ago accepted that I never will be an artist.

But I can get by with graphics as I hope all the pictures on this site show. Either they are screenshots or comes from sites like pixabay.com and unsplash.com. Both are excellent sources of free images.

Sometimes though I have to do a lot of editing. MonoGame requires bitmaps for fonts. So I’ll take a free monospaced font and choose a size and create a sprite sheet from it.

But sometimes the tools I use are less than perfect. I never mastered or bought PhotoShop. Instead I used software like PhotoDraw 2 (from Microsoft in the early 2000s) or before that Macromedia Fireworks. But these are quite old and instead I’ve been looking around for something a bit newer.

There are quite a few open source graphics editors and if you look closely at my er artwork you can see at the bottom that this was taken from one such package called GrafX2. One reason for including it is that it’s coded in C and it reminds me of the granddaddy of drawing packages : Dpaint. As we’re talking over 30 years ago, I don’t know how many will remember it.

How to use indexed sequential files

How to use indexed sequential files

Files
Image by Pontep Luangon from Pixabay

This was a big thing long before PCs existed but you don’t see it so much nowadays.  Say we have a lot of static data, perhaps text strings which can vary in length from a few bytes to hundreds of bytes long. What is an efficient method to store them, i.e. in both space and time?

The answer is ISAM (Indexed Sequential Access Method)  which sounds more complicated than it is. We will use two binary files- one is the data file and one is the index file. The data file holds the raw text strings. We’ll write the raw strings using the C file write. At the same time as write them, we also build up an array of structs. This struct will look something like this:

typedef struct {
  int id;
  unsigned long offset;
  unsigned long length;
} indexRec;

The id could be a char * string. It’s just a way to search for and find the data.

As each text string is written to the data file we populate a struct with the file offset and length. Eventually after all strings are written you can write the arrays of structs to the  index file.

Then anytime you wish to read text strings back, load the structs into an array in ram and scan for the matching id then call fgetpos with offset (this moves the file pointer to the specified byte offset) and read in the length number of bytes from the data file.

An even simpler approach

If you just use an index number then you can scrap the id field and instead store the index file as a collection of offset and length fields. To read string #100 just do a fgetpos to byte at 100 * 8 (four for the size of offset plus four for the size of length)  in the index file, read the eight bytes for offset and length then do a fgetpos in the data file to the offset and read in length bytes as before. Very efficient and very fast. Just two reads in two files and one of those is only eight bytes.

If you wish to change the text strings in the data file, use the same method to retrieve them. If the new string is smaller then just write it and change the length field of the index record and rewrite it. If the new string is longer than the old, write it on to the end of the data file and change the index offset and length fields and rewrite them in the index file.

Both of these edit methods (shorter or longer string edits) will ‘lose’ bytes in the data file. When replacing with a shorter string and adjusting the length, the extra bytes that were in the previous string are no longer referenced. With a longer edit the entire previous string is no longer referenced.

Reclaim lost bytes

However it’s very easy to compact the data file and reclaim these lost bytes. Just process the index file and read each string and write them on the end of a new initially-empty file.  You also change each index file record to have the new offset and length of each string in the new data file. Once it’s rewritten just delete or backup the old data file and rename the new data file to be the one used from now on. Depending on how often the data file is edited, you will need to “compact it” every few days or weeks. But compacting is a pretty quick process, even for mega byte or larger sized files.

I used this technique albeit in Turbo Pascal not C to store game data for postal games I wrote back in the late 1980s. Games that are still run today but on the internet, not by post. For example in a map location there can be several parties of adventurers. The file record for that location has a file pointer to the start of a chain of party file ptr records. Each index file of adventurer parties has a binary file offset to the party in a binary file and a file ptr (or -1 if the end) of the next party’s file pointer. Like a pointer linked list but using file pointers instead of real pointers. Similarly the map location has a file pointer to a dungeon if one exists in this location (or -1 if it doesn’t).

This technique kept the map file fairly small but there were lots of binary file pairs for parties, dungeon, characters (in parties), and towns and shops in towns. Who needed a database? I didn’t… (That’s cos databases didn’t really exist back in the day. Had they existed I might have used them… maybe).

The minus one problem

In the struct definition, you’ll notice that I use unsigned longs for file pointers and length. There is no -1 for unsigned longs. It’s 4294967295. Using this as an end of chain pointer is ok because it is never going to be used as an offset. If I had used signed numbers then I could have used -1 but remember when I wrote this, it ran on a 16 bit computer so I used 65535 instead of -1. I could easily get binary files 40 Kb or 50 KB in size, so a signed number would have overflowed after 32767 bytes.