Category: Techniques

I know a fair bit of C but

I know a fair bit of C but

The letter C in fancy script
Image by Gordon Johnson from Pixabay

There are a lot of subtleties that you only pick up with experience.  I was pleased to find a blog entry by a bloke Tom M on “Everything I wish I knew when learning C” which is well worth a read.

I’m not going to copy anything from it except for this little snippet below one below. For the rest, you’ll have to read his blog post.

char signedness

All other integer types default to signed, but bare char can be signed or unsigned, depending on the platform.

As said char is an integer type but unless you are doing stuff like ++ or — when its value can overflow according to being signed or unsigned, it’s not really a problem. And unless you are writing code that runs on wildly differing platforms, you can probably safely assume that a char is the same as a byte and has 8 bits. On those other platforms, I’d suggest you read the answers to this Stackoverflow question.

++/– Operators work on floats and doubles

++/– Operators work on floats and doubles

laptop computer with an editor
From Instant Images

No matter how much I use C there are still things I thought I knew but find out otherwise. The latest one is that you can use ++ or — on float and double variables.

Here for instance is a short nonsense program that I compiled and ran with Visual Studio on Windows. As you’#ll notice, it increments and decrements floats and a double.

The danger with using this is that you might get rounding errors. When I ran it on Windows, I didn’t which surprised me. I will have to try this on Linux.

#include <stdio.h>

void main()
{
    float c = 1.0f;
    float cin = 10000.0f;
    double d = 2.0;
    int i = 0;

    while (cin != c)
    {
        i++;
        cin = c;
        c--;
        d++;
    }
    printf("%i %e %e\n", i, c, d);
}
Using JSON as a datastore in C#

Using JSON as a datastore in C#

Shapes
Image by Gerd Altmann from Pixabay

For some not too complex applications, JSON can be a very handy way to store data rather than say using a database. It also has the advantage of storing data of varying sizes. For instance Lists with varying numbers of items. I created a Saveable generic class below that you use as an ancestor class for that you wish to Save/Load an IList of whatever.

 

 

    public class SaveAble<T>
    {
        private string _error = "";
        string LastError()
        {
            return _error;
        }
        public IList<T>? Load(string filePath)
        {
            if (!File.Exists(filePath))
            {
                Log.Error("Missing file {filePath}");
                _error = $"Missing file {filePath}";
                return null;
            }

            var content = File.ReadAllText(filePath);
            if (string.IsNullOrEmpty(content))
            {
                Log.Error("{filePath} file is empty");
                _error=$"{filePath} file is empty";
                return null;
            }

            return JsonSerializer.Deserialize<IList<T>>(content, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            })!;
        }

        public bool Save(string filename,IList<T> collection)
        {
            var options = new JsonSerializerOptions
            {
                WriteIndented = true,
                PropertyNameCaseInsensitive = true
            };
            try
            {
                var bytes = JsonSerializer.SerializeToUtf8Bytes(collection, options);
                File.WriteAllBytes(filename, bytes);
                return true;
            }catch (Exception ex)
            {
                _error = $"Exception:{ex.Message}";
                return false;
            }
        }

    }

Just define your class MyClasses from SaveAble<MyClass>

where MyClass is the class you have a List of. Then you can do

MyClasses myclasses;
myclasses.Save("filename",List<MyClass>) and

List<MyClass> list = myclasses.Load("filename");

It is fast. On my PC (now six years old), it can load a 99,000 line JSON file in well under a second.

So what do I think of C++ compared to C?

So what do I think of C++ compared to C?

Software
Image by Gerd Altmann from Pixabay

I learnt C++ 30 years ago (1991)  and C about 10 years ago.  Mind you I’d had several years of Pascal by then including some OOP (Object Oriented Programming) so it wasn’t that big a thing to learn C++ after Pascal.

For me it’s the objects and the template structures like vect that make the difference. Most C programs that I’ve written don’t really progress beyond using an array of structs. Asteroids, which at 2,200 lines long used a few of those but that was it.

In fact if I wanted any more complicated data structures in C programs, I’d either have to use a 3rd party library or roll my own using pointers.

Programs I’ve written in C# probably use List<Class> more than any other data structure with Dictionary<string,Class> a close second. It really depends upon the type of program you are writing. A lot of mine are reading from a text file or database file, holding data in memory then outputting results.

C++ offers more advanced data structures than C and I spent a fair bit of time rewriting Asteroids replacing all the array of structs as arrays of objects.  Inheritance isn’t that big a thing in OOP but it was handy here because I was able to initially have Asteroids, Space Ships, Bullets and Aliens classes all inherit from a moveable base class. That class had all the code for rotation, movement etc. I found though that C++ could be a real pain when trying to do comparisons between different superclasses and eventually switched from inheritance to composition so those classes had a moveable object instead.

The downside to C++ is remembering if you are copying or moving objects. Not a problem you have in C. One of the interesting problems is how you track the number of active Asteroids which can change from frame to frame. In C I used a fixed array of structs with a field showing whether it was active. Using a vect though and pushing and popping asteroid objects would probably take longer.

My PC is broke… plan b

My PC is broke… plan b

Linux Tux
Image by FreeCliparts from Pixabay

I repurposed my wife’s old Toshiba laptop a year ago, installing Ubuntu 20.04 LTS on it to replace Windows 10. Today my Windows PC broke. It appears that the cooler has given up after five and a half years faithful service. The warranty of course was only for five years… I just have to make sure it is the cooler and not the PSU has gone and get it replaced.

I know it was overheating because I rebooted after 30 minutes and into the UEFI BIOS. There I watched the temperature climb at a rate of 1C every second. When it hit 75 C and the text turned red, I knew that it was overheating.

So I dug out the Toshiba and upgraded Ubuntu on it finally figuring out the password after 20 or so tries. Only 560 packages needed upgrading! That took a while and I’ve also been installing other software since. My VS Code was that old that it won’t actually update. When I did the Linux version of Asteroids I tested it on here.  It seems I have to download a recent version of VS Code which will let it upgrade with apt.

It shouldn’t but it never fails to surprise me how quick Linux is. This laptop has an I3 CPU and a hard disk and is about . It has 4 GB of RAM; I upgraded that a couple of years ago to try and speed up Windows. Even after upgrading Windows 8 to 10 and removing some of the Toshiba bloatware, it was never that quick. But now it flies.

Thankfully Chrome had the password to the site so I was able to login and write this from the laptop. I may have to do without my Windows PC for a week or two…

Widening the scope of this website

Widening the scope of this website

Chaso
Image by levelord from Pixabay

When I first started, I wanted this to be for two purposes. Learning C programming and learning games programming. Apart from a few more tutorials that I have to complete, it’s mostly complete as far as C goes.  I still have to finish my 2nd e-book which is now up to chapter seven. I received some advice after my first eBook and so I’ve completely revised the second one to have a lot more explanation.

But after a year of doing mostly C stuff (and a bit of C#), I have found it harder to get things to write about on C.  I’ve been revising what I’m doing in games programming and so am looking about. I do like Blazor but am going to try an alternative approach. If I succeed, you’ll hear a lot more about it.

The picture probably represents the contents of my head!

 

There’s always someone inventing something better

There’s always someone inventing something better

JSON Logo
JSON Graphical Logo

In this case, I’m talking about better than JSON. JSON was invented as an alternative to XML which was invented as a way for computers to send data in a human readable form. Unfortunately XML is a pretty bloated format. Putting data into XML can make it five or six times larger.

Plus by the time XML was coming into common use in the mid-late 90s, there was a horrible letter soup of associated acronyms. It sort of appeared at the same time as Java and the whole XML ecosystem was lapped up by big business. JSON was born as an alternative method and it became very popular as JavaScript was growing at the same time, JSON is short for JavaScript Object Notation.

Now there’s MessagePack an alternative to JSON. It’s supposed to be faster and smaller than JSON. I came across it while looking at SignalR, a way to send data between clients and servers and used in Blazor and .NET websites.  It must have been around for a while as it was used back in 2011.

There’s now 50 programming language implementations including C at the bottom of the MessagePack home page although there’s over 100 but that includes several implementations for the same language.

If you have to move data between two computers, or maybe two processes on the same computer, you want it to be as small as possible and that’s what MessagePack allows.

 

Learning a programming language is not so easy

Learning a programming language is not so easy

Never stop learning
Image by Gerd Altmann from Pixabay

When I started, back in the dark ages there weren’t many programming languages about. It was a choice of BASIC, Fortran, C, Pascal and Cobol or some obscure languages apl, lisp, snobol etc. At Uni I learnt BASIC in first year then Pascal. We touched on Cobol in one course, enough to put me off it for life. We also did one semester on assembly language for a 6800 CPU. That was fun and probably helped me to learn 6502 and Z80 a few years later.,

Back then once I started learning other languages, it was long before the web existed. Programming languages came with manuals – user guides, reference guides. So you could learn enough to get started and then dip into the reference guide as and when you needed.

But since the Web appeared, the manuals no longer exist as printed books. But what I’ve noticed is, it gets harder to acquire a new technology if you are not working in it fulltime. I learnt PHP and HTML twenty years ago and reinforced that learning by creating websites. But now technologies like Blazor and ASP.NET MVC are quite a bit more complicated.  I’m doing  Udemy course on Blazor with over 200 lessons (most about 5 minutes long) and have only got up to lesson 55. Finding the time is probably one of the hardest things.

C is probably one of the easiest programming languages to learn but any other language or complicated technology is going to take a lot longer. I think It should be easier. There is an immense amount of free material on the web including sites to pose questions (StackOverflow), low cost courses (Udemy), free videos (Youtube) and yet it doesn’t seem easier.  Back pre-web you had to pay for programming languages. But unless you are a student or have a lot of spare time to study, it can be slow learning new stuff.

 

So I timed a short program with /Gd and /Gr

So I timed a short program with /Gd and /Gr

StopWatch timings
Image by Michal Jarmoluk from Pixabay

This was the follow up to yesterday’s post about seeing if changing the function calling convention, switching from stacked parameters to passing them in registers made a difference in execution time.

This was the program I used.

#include <stdio.h>
#include "hr_time.h"

int add(int a, int b, int c,int d,int e) {
	return a - b * 2 + c * 3 + d * 3 + e * 5;
}

int __cdecl main() {
	int total=0;
	stopWatch s;
	startTimer(&s);
	for (int i = 0; i < 10000000; i++) {
		total += add(i, 5, 6, i, 8);
	}
	stopTimer(&s);
	printf("Value = %d Time = %7f.5\n",total, getElapsedTime(&s));
}

Pretty similar to the one I did yesterday except with two more parameters in the add function and my Windows high-res timing code. I’ve extracted the two timing files (hr_time.h/.c) from the asteroids and it’s in the LearnC folder on GiHhub.

As before this was compiled as x86. Also I tried it first compiled as release. This means the optimizing compiler has its way and I got virtually identical for cdecl (/Gd), fastcall (/Gr) and even safecall (/Gz).

Disassembly of the machine code revealed that the optimizer had moved the function code inline in the for loop and this negated the call code. So I did it again in debug mode. Here there was a clear difference. The times for fastcall were 0.259 while the cdecl (the default) was 0.239 which is about an 8% speed increase. Safecall was roughly the same execution as cdecl. So the lesson seem to be don’t use fastcall.

I think I need a more complicated program which should be compiled in release mode but where optimization doesn’t transform the function into inline code. Perhaps making the function longer would do it so the function machine code would be too long to fit in a L1 cache.

Interestingly the release code execution time was 0.005557 seconds, almost 50 x faster than the debug time.

How much faster is C code compiled with fastcall?

How much faster is C code compiled with fastcall?

Setting fastcall in VS 2019Something I read about the other day was the __fastcall convention. In Visual Studio you enable this with the /Gr flag and in gcc (it’s __attribute__((fastcall)). For clang it’s fastcall but see this.

So what does fastcall do? It changes the calling convention, so instead of pushing parameters to a function on the stack, it passes them in the registers starting with ECX then EDX and so on.  Let’s look at an example.

#include <stdio.h>

int add(int a, int b, int c) {
	return a + b * 2 + c * 3;
}

int main() {
	printf("Add(4,5,6)=%d\n", add(4, 5, 6));
}

This is the disassembly code from VS 2019. I pressed F10 to start debugging then Debug => Windows => Disassembly to get the listing. Note thei is x86, ie 32-bit.

005B18DC  lea         edi,[ebp-0C0h]  
005B18E2  mov         ecx,30h  
005B18E7  mov         eax,0CCCCCCCCh  
005B18EC  rep stos    dword ptr es:[edi]  
005B18EE  mov         ecx,offset _9831A1D6_test@c (05BC003h)  
005B18F3  call        @__CheckForDebuggerJustMyCode@4 (05B131Bh)  
	printf("Add(4,5,6)=%d\n", add(4, 5, 6));
005B18F8  push        6  
005B18FA  push        5  
005B18FC  push        4  
005B18FE  call        _add (05B1023h)  
005B1903  add         esp,0Ch  
005B1906  push        eax  
005B1907  push        offset string "Add(4,5,6)=%d\n" (05B7B30h)  
005B190C  call        _printf (05B10D2h)  

Now if I build it after setting the /Gr flag. In Vs 2019, on the project property pages, click advanced then the Calling Convention and switch from cdecl (/Gd) to –fastcall (/Gr).

008118EC  lea         edi,[ebp-0C0h]  
008118F2  mov         ecx,30h  
008118F7  mov         eax,0CCCCCCCCh  
008118FC  rep stos    dword ptr es:[edi]  
008118FE  mov         ecx,offset _9831A1D6_test@c (081C003h)  
00811903  call        @__CheckForDebuggerJustMyCode@4 (081131Bh)  
	printf("Add(4,5,6)=%d\n", add(4, 5, 6));
00811908  push        6  
0081190A  mov         edx,5  
0081190F  mov         ecx,4  
00811914  call        @add@12 (0811276h)  
00811919  push        eax  
0081191A  push        offset string "Add(4,5,6)=%d\n" (0817B30h)  
0081191F  call        _printf (08110CDh) 

I’ve highlighted the differences in bold. However the function Add is also different as the fastcall version doesn’t have to pop parameters off the stack.

Note, to get this to compile I had to prefix main with __cdecl. Using /Gr means that every function in the program uses registers and that’s not allowed with main as it’s called from Windows end must use the cdecl (default stack passing) convention.

This is what main looks like now.

int __cdecl main() {

Notes

This is only for 32-bit. 64-bit code is done somewhat differently so possibly wouldn’t be that different. Next I have to write a program that does lots of function calls and use high precision timing to see how much of a difference it makes. To be continued.