Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

C Tutorials


chuchoide
 Share

Recommended Posts

If you refer to the Moodle website you will see there is a Moodle for Mac and a Moodle for Windows and as far as I know, Anthony uses Linux but does own a Mac. I do not know if Moodle will work between the 2 OS's though and there is also the issue of who will host the web server?

I will host the web server if I must.

Regards,
  Dewald
Link to comment
Share on other sites

  • Replies 51
  • Created
  • Last Reply

Top Posters In This Topic

It's really awesome except for the time difference. The first lesson was about 6 hours long and was till 2 AM and the second about 2 hours.

But it is really fun, especially the assignments.

Regards,
  Dewald
Link to comment
Share on other sites

@N00DLES:

> Off-topic, but, there's this thing called Moodle, and you can set assignments, courses, etc up.
>
> Easy to use, and it's a nice system.

No, thank you. I'd rather roll out my own article system written in C89 with an UBB/BBC-parser with unseen power.

@N00DLES:

> Yeah. It's free. You should use it, and people would be able to learn C off of you. ;)

I ought not to. Stop enforcing stuff I don't even want to run on my web server. Processors are designed to interpret machine code, not PHP. It's already bad that the majority of clients have to interpret tons of XML, CSS and Javascript.

Regards,
  Stephan.
Link to comment
Share on other sites

Not entirely true. It is more of the interaction that you want instead of reading a bunch of tutorials. It would be way better to learn C by playing with a programs code or having like a "tutor" to guide you. I like to read tutorials in my spare time as they give you that one step ahead.
Link to comment
Share on other sites

@Mikekan13:

> I have been watching/reading tutorials on C but I think I will learn the most when I get my hands on this Eclipse C engine.

Not true: the majority of proper design should be learnt by reading the appropriate course material. Reading through a compiler's source code is not going to teach you anything, unless you know compiler theory. The same counts for every other piece of software.

The game engine might teach you how certain things should be done, sometimes could be done, but it will not teach you why certain things were done like that, and neither will it be able to teach you certain concepts.

Regards,
  Stephan.
Link to comment
Share on other sites

> Not true: the majority of proper design should be learnt by reading the appropriate course material. Reading through a compiler's source code is not going to teach you anything, unless you know compiler theory. The same counts for every other piece of software.
>
> The game engine might teach you how certain things should be done, sometimes could be done, but it will not teach you why certain things were done like that, and neither will it be able to teach you certain concepts.

There are different ways to learn. I learn best by hands on tinkering. If I don't understand why something is done a certain way in the code that I am studying then I look up the theories behind it online.
Link to comment
Share on other sites

@Mikekan13:

> There are different ways to learn. I learn best by hands on tinkering. If I don't understand why something is done a certain way in the code that I am studying then I look up the theories behind it online.

I'm sorry to say but "tinkering" can actually break an entire design within one's finger snap. It's not recommended to start off with just changing a few things here and there. It's better to first start with the majority of theory, and then actually do the practice. And sometimes there simply is no theory online for certain concepts, unless I document it (e.g. why certain functions require you to allocate a buffer and why they actually tell you the size to use, which is typically unseen behaviour in most code).

Regards,
  Stephan.
Link to comment
Share on other sites

@S.J.R.:

> I'm sorry to say but "tinkering" can actually break an entire design within one's finger snap. It's not recommended to start off with just changing a few things here and there. It's better to first start with the majority of theory, and then actually do the practice. And sometimes there simply is no theory online for certain concepts, unless I document it (e.g. why certain functions require you to allocate a buffer and why they actually tell you the size to use, which is typically unseen behaviour in most code).
>
> Regards,
>   Stephan.

Okay so where would I read up on theories and all this stuff? Me reading this book is kinda useless as he doesn't explain WHY its better then that way and ETC. I just need an outside source to tell why.
Link to comment
Share on other sites

@Admiral:

> It's been covered a few times [here](http://www.touchofdeathforums.com/smf/index.php/topic,72573.0.html) and [here](http://www.touchofdeathforums.com/smf/index.php/topic,350.msg758181.html#msg758181).
>
> Generally speaking, we're trying to avoid the overhead of object-oriented programming while remaining as small and fast readably possible.

Just out of curiosity, why avoid OOP overhead? I mean sure, multiple instances of class constructors being called seems intense, but all it is doing is setting variables in a more organized manner.

Lets say we have classes A and B.

```
class A
{
private:
    int x;

public:
    A(void)
    {
        x = 0;
    }

    A(int X)
    {
        x = X;
    }
};

class B : public A
{
private:
    int y;

public:
    B(void)
        : A()
    {
        y = 0;
    }

    B(int X, int Y)
        :  A(X)
    {
        y = Y;
    }
};
```
In this example, the overhead you are trying to avoid is apparent. HOWEVER, I am almost pretty sure you can overcome that by creating pure virtual functions and allocating each object directly to the heap. Then at that point, the overhead is just one single pointer  :embarrassed:
Link to comment
Share on other sites

@JeffSventora:

> - snip -

Good, I have a practical test for you. I'm giving you a few members to put into either a class or a structure (I don't really care) called PixelFormat. I will only tell you the members to add and what type they are. It's your task to set up a class or structure containing those members, with an explanation of why you wrote it like that.

The following members are of type Uint8: iBitsPerPixel, iBytesPerPixel, iRloss, iGloss, IBloss, iAloss, iRshift, iGshift, iBshift and iAshift.
The following members are of type Palette * (pointer): objPalette.
The following members are of type Uint32: iFormat, iRmask, iGmask, iBmask, iAmask, iReferences.
The following members are of type PixelFormat * (pointer): objNext.

If you finish the test, then please post your result, and I will also explain you why your example is one of the most horrible OOP uses ever.

@JeffSventora:

> In this example, the overhead you are trying to avoid is apparent. HOWEVER, I am almost pretty sure you can overcome that by creating pure virtual functions and allocating each object directly to the heap. Then at that point, the overhead is just one single pointer  :embarrassed:

OOP programmers tend to avoid low-level details. Here is a good example of that: heaps shouldn't be overused, especially not for small granularities. Memory fragmentation is one of the biggest problems in software design, because most people merely use a heap. The stack should be used for in-scope data and small granularities. The heap should only be used for big granularities and out-of-scope data. In fact, one should micromanage the heap for optimal memory usage.

Regards,
  Stephan.
Link to comment
Share on other sites

@Bloodmorphed:

> Okay so where would I read up on theories and all this stuff? Me reading this book is kinda useless as he doesn't explain WHY its better then that way and ETC. I just need an outside source to tell why.

I haven't found any good material concerning that. I learnt most techniques for proper programming from presentations, references, articles, etc.

Regards,
  Stephan.
Link to comment
Share on other sites

Interesting, I completely agree, it was just the only method I could come up with from memory to evade the overhead. But surely you are correct.

As far as the little test, I'm not exactly sure how in depth you wanted me to go, but I went ahead and defined the structure with all of the members defined, the constructor prototyped as well as the trilogy.

```
struct PixelFormat
{
private:
    Byte iBitsPerPixel, iBytesPerPixel, iBytesPerPixel, iRloss, IBloss, iAloss, iRshift, iGshift, iAshift;
    Palette *objPalette;
    UInt32 iFormat, iRmask, iGmask, iBmask, iAmask, iReferences;
    PixelFormat *objNext;

public:
    /* Constructors */
    PixelFormat(void);

    /* Trilogy of Evil */
    ~PixelFormat(void);
    PixelFormat(const PixelFormat & PF);
    PixelFormat & operator=(const PixelFormat & PF);
};
```
Link to comment
Share on other sites

The first task is to set up a structure (I ignored the fact you used a class though, since that was not my intention) with all the members sorted by size (in C89):
```
#include // Uint8 & Uint32.
#include // Palette.

struct PixelFormat;
typedef struct PixelFormat PixelFormat;

struct PixelFormat
{
    PixelFormat *objNext;
    Palette    *objPalette;
    Uint32      iFormat;
    Uint32      iReferences;
    Uint32      iRmask;
    Uint32      iGmask;
    Uint32      iBmask;
    Uint32      iAmask;
    Uint8        iRloss;
    Uint8        iGloss;
    Uint8        iBloss;
    Uint8        iAloss;
    Uint8        iRshift;
    Uint8        iGshift;
    Uint8        iBshift;
    Uint8        iAshift;
    Uint8        iBitsPerPixel;
    Uint8        iBytesPerPixel;
};

```
The worst-case size on 64-bit architectures for this structure is: 50 + 6 (end of structure padding) bytes.
The worst-case size on 32-bit architectures for this structure is: 42 + 2 (end of structure padding) bytes.

The reason why data should be sorted by size is the simple reason that you want to avoid padding at all costs, except for the padding at the end of structure. By sorting it from large to small you get minimal memory usage.

Consider this example (since you actually sorted by type, so the only issue you have is that you have inline padding):
```
struct A
{
    Uint8 iX;
    Uint8 iY;
    Uint32 iZ;
    Uint8 iU;
    Uint8 iV;
    Uint32 iW;
};
```
If you sort it, you'll get this:
```
struct A
{
    Uint32 iZ;
    Uint32 iW;
    Uint8 iX;
    Uint8 iY;
    Uint8 iU;
    Uint8 iV;
};
```
The comparison is clear: the latter example only has minimal end of structure padding, whereas the prior might have several occurrences of inline padding (depending on what the compiler does).

Using structures is a way of interpreting bytes of data as several types in sequence, i.e. a group of data. By introducing methods, you get classes. The thing is: most people lose their focus when dealing with OOP and aim for a code-oriented approach instead of a data-oriented approach, and I just showed you one simple rule of the latter (sorting types appropriately for optimal memory usage).

Your worst enemy when programming C/C++ nowadays is the cache. Cache lines are usually only 64 bytes, therefore structures should be 64 bytes at most. Sorting is one such technique, but another is to use pointers to other structures, to group data defined by focus (e.g. a camera would have a lens, consider those two structures with each specific values, instead of having one big structure, it might be more appropriate to have two separate structures that each fit in such a cache line). But it is not always a bad idea to use structures bigger than 64 bytes though, just don't go mad with it.

Caches are important because they allow fast memory access. Every time you access data from memory, it gets loaded into the cache if it isn't there. The cost might be 100 cycles to about 600 cycles in most cases. When that happens, you have a cache miss. Once the data is in the cache, you should re-use it as much as possible (the opposite of a cache miss is a cache hit), since the cache only takes few cycles to access. Operating on megabytes of data is therefore a very stupid idea, that happens often though when linear algorithms are implemented.

There is a second cause of performance loss: libraries. When calling functions or methods in your own code domain, the compiler can optimise them. When you call functions or methods outside your code domain (e.g. in a library), you'll get performance hits (since the compiler cannot optimise library access). There is a code barrier between your programme and the library that cannot be optimised (this happens often between programmes, libraries, kernel code and drivers). Another reason why one should aim for data-oriented design.

Your class example itself was just a horrible example because it is completely code-oriented. Put it in another library, and you'll get some performance hits whenever you use it. Not to mention the fact that it operates on a single integer of data, instead of multiple data types.

Object-oriented programming, and therefore code-oriented programming usually makes people forget that code can be slowed down by cache misses and therefore memory. In fact, a 3GHz processor is completely useless when you get constant cache misses and would just perform as worse as a 1.6GHz processor.

Regards,
  Stephan.
Link to comment
Share on other sites

@S.J.R.:

> -snip-

Stephan I think I love you(lol! :P). I mean you explain everything in detail and quite frankly enough to were I can understand it.

I think you should write a basics about "C" article/short book. For people like me and many others. I think perhaps you could do better then what I have now. Anyways, when you have time I think you should do that. Or something of the sort.
Link to comment
Share on other sites

@Bloodmorphed:

> Stephan I think I love you(lol! :P). I mean you explain everything in detail and quite frankly enough to were I can understand it.
>
> I think you should write a basics about "C" article/short book. For people like me and many others. I think perhaps you could do better then what I have now. Anyways, when you have time I think you should do that. Or something of the sort.

If I recall correctly he did say that once he has finished coding the back-end of his site he will be posting articles there for us.

Regards,
  Dewald
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share


×
×
  • Create New...