Welcome, Guest. Please login or register.

Author Topic: Learning C with the Amiga  (Read 32363 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #14 on: February 07, 2007, 10:45:17 PM »
Quote
Karlos and YOU assumed I was responding to her "code" when I was actually responding to her prior set of several questions


I was responding to:

Quote
Even if a structure contains an array, the value within the structure representing the array is a pointer.


If I misunderstood what you meant by that, feel free to correct me.

However, embedding a fixed length array of X versus a plain pointer to X within a structure are still completely different cases, as I pointed out earlier.

In other words, you could, if you felt so inclined, pass a fixed length array by value simply by wrapping it in a structure and passing that by value. The entire array would be copied in that case.
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #15 on: February 07, 2007, 10:54:38 PM »
@Koaftder

For properly portable code, I cannot stress this enough. For file IO, always write code that marshalls your binary data properly when loading and saving if you want to ensure it can be loaded on another machine. Write functions that know how to write your structures to a file stream and ones that know how to read them. Doens't need to be text based (and shouldn't be really for binary data unless you want it rendered human readable).

When performing the specific IO, you sould also consider saving blocks of "same sized" data (eg a bunch of 16-bit words) together and not mix them up with IO on elements of other sizes. This only matters if you plan to ever load the data on a version of the code compiled with a different endian representaion, however, in which case you need to know how big each binary element is in case you need to byteswap any of it.

The cost of doing this is totally mitigated by the performance hit IO operations tend to give anyway so it's rarely, if ever, perceptably slower.

Simply dumping structures is easy for quick stuff that doesnt need to be portable. Your structures may have holes in them or not, depending on packing but as those holes never contain meaningful data anyway it doens't matter except in space waste terms. Simply reordering your structure layout to put all the same-sized member elements together, largest first, eliminates this anyway.

Of course, if you do reorder your structures in this fashion, the idea of saving their members as blocks of same sized data within your functions becomes that much simpler too ;-)
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #16 on: February 08, 2007, 12:20:08 AM »
@Koaftder

There's nothing "specific" in the STL or anything for data serialization, unless you count using the C++ stream classes and implementing the appropriate operator<<() and operator>>() for your classes. Said streams are generally character based, however.


What I did was to create classes something like this (simplifed here as the full system was a complete binary safe OOP storage engine)

Code: [Select]

class OutputStream {

  private:
    // write the current architectures' signature
    // into the file header
    bool writeHeader();

  public:
    bool open(const char* fileName);
    void close();
    size_t write8(const void* src, size_t num);
    size_t write16(const void* src, size_t num);
    size_t write32(const void* src, size_t num);
    size_t write64(const void* src, size_t num);

    //...
};

class InputStream {

  private:
    bool swapEndian;

    // read the architecture signature
    // from the file header
    bool readHeader();

    // normal readers
    size_t read8Norm(void* dst, size_t num);
    size_t read16Norm(void* dst, size_t num);
    size_t read32Norm(void* dst, size_t num);
    size_t read64Norm(void* dst, size_t num);

    // readers with endian conversion
    size_t read16Swap(void* dst, size_t num);
    size_t read32Swap(void* dst, size_t num);
    size_t read64Swap(void* dst, size_t num);

  public:
    bool open(const char* fileName);
    void close();
    size_t read8(void* dst, size_t num);
    size_t read16(void* dst, size_t num);
    size_t read32(void* dst, size_t num);
    size_t read64(void* dst, size_t num);

    //...
};

// typical implementation
inline size_t InputStream::read32(void* dst, size_t num)
{
  return swapEndian ? read32Swap(dst, num) : read32Norm(dst, num);
}

class StreamStorable {

  public:
    virtual bool write(OutputStream& s) = 0;
    virtual bool read(InpputStream& s) = 0;

    // ensure a proper destructor is called if we
    // ever delete a StreamStorable*
    virtual ~StreamStorable() {}
}



The idea here is that the OutputStream has methods for writing 8/16/32/64 bit data. It always writes a header to the file first, consisting only of a few bytes of data that include information about the current machines architecture, the type of file data and so on.

The InputStream class, upon opening such a file, checks to see if the written signature is endian compatible with the current machine or not and sets the swapEndian flag accordingly, which in turn dictates which multibyte IO routines are used for reading.

Last but not least, objects that needed to be saved to / read from said streams would implement the StreamStorable interface, thus:

Code: [Select]


class Something : public StreamStorable {
  private:
    sint32 foo[2];
    sint16 x;
  public:
    bool write(OutputStream& s) {
      return (s.write32(foo,2)==2 && s.write16(&x,1)==1)
    }

    bool read(InputStream& s) {
      return (s.read32(foo,2)==2 && s.read16(&x,1)==1)
    }
};

//....


Something blah();
OutputStream out("ram:foo.dat");
blah.write(out);
out.close();



This is actually a total oversimplification of what was really done since the actual Storable interface would write a header of its own and store a small amount of other metadata, including the total size, inclusive of anything dynamically allocated, so that the read functions could completely reconstruct an object that migh have dynamically allocated data in them. However, I hope it gets the general idea across.

int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #17 on: February 08, 2007, 12:25:58 AM »
Quote

CannonFodder wrote:

C++ is just a ¨bida¨ Karlos! :-P


Yes, a bloody good one too! All the control (and more) you get in C with a thousand times the finesse.
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #18 on: February 08, 2007, 12:32:21 AM »
Quote

koaftder wrote:
99 out of 100 programmers won't beat the C compiler when writing an algorithm in assembler.


If you have a good understanding of your target you can usually optimize a few functions in assembler and manage it better than the compiler. However, you sould only attempt this when you have exhausted optimizing the C/C++ code itself and it still isn't fast enough.

It should always be an aggressive-performance-optimization driven last resort, however and furthermore you should never throw your original code away (conditionally compile it out or have a different fork without asm in it) - you never know when you might have to port it to another system :-)
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #19 on: February 08, 2007, 09:33:29 AM »
No, it's not complete as I was focusing on the actual serialization mechanism and not polymorphism in general. Yes the actual class has a virtual destructor. I'll add it to th4e example for completeness ;-)
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #20 on: February 08, 2007, 11:26:35 AM »
Quote

CannonFodder wrote:

C++ is the Shia to Islam´s C? ;-)


/me runs very very fast!!


No. C++ was the final revelation that perfected the language. C itself is more like your Torah/Gospel :-P

/surreal
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #21 on: February 08, 2007, 11:39:08 AM »
Quote
I've heard people describe C as a better assembler, but that doesn't make it a poor language to learn.


Quite the opposite. This is why it is an excellent language to learn as you gain true insight into the low level behaviour of the machine that higher level abstractions deny you.

I've never met a skilled C/C++ developer yet that writes inefficient or sloppy code regardless of the language they are using. In my experience, the same cannot be said for those that come purely from higher level language backgrounds.

Languages that require you as the developer to take ownership of efficiency and resource management tend to be the best to learn. Languages that take over resource management are good once you understand how said management works.

I regularly see things like this in java code:

Code: [Select]

while (isNotDone()) {
  Something blah = new Something();
  // ...
  blah.doSomeOperationThatDoesntAlterObjectItself();
  // ...
}


in places where

Code: [Select]

Something blah = new Something();
while (isNotDone()) {
  // ...
  blah.doSomeOperationThatDoesntAlterObjectItself();
  // ...
}


would perform the exactly the same job. The developer is utterly oblivious to the cost of repeatedly constructing an object that gets used in a non-destructive way once. Instead, all they know is "best to keep variables as local as possible" because they have not learned anything about resource management since they have never used a language where they are required to manage resources themselves.

From a high level, their code is well structured, very OOP, properly implementing known patterns where they apply but the physical implementation of their code is full of inefficient resource clobbering examples like those above.
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #22 on: February 08, 2007, 11:41:32 AM »
Objective-C is more like Sikhism, where two syntactically unrelated languages were merged to create a new one...
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #23 on: February 08, 2007, 12:52:38 PM »
Quote
I would say that JAVA is the final revelation that perfected C++.


Complete and utter bilge. Some java shortcomings from the POV of a C++ developer:

Efficient concrete types cannot be realistically implemented as all calls are virtual, all objects are polymorphic.

Inheritence is singular and public level only.

No real control over object destruction.

No operator overloading. Except for the inbuilt StringBuffer which has an implementation of "+", thus destroying their own argument against allowing it.

I used to say "full support for generic programming (templates)" but Java has added generics, which use something very similar to C++ template syntax. Which they used to criticise very heavily ;-)
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #24 on: February 12, 2007, 03:17:28 PM »
To be fair, designing my own libraries that wrapped up the OS behind my own class interfaces was more fun than writing the applications :lol:
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #25 on: February 12, 2007, 10:13:56 PM »
You know, I've written countless thousands of lines of C and C++ code by now. You know how many times I actually *needed* to directly concatenate a string for anything (as opposed to just reading/writing to some device or setting properties of some object)?

I can probably count it on the fingers of one hand. Unless you are specifically working on code that makes heavy use of text parsing I really think the issue is blown out of proportion.
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #26 on: February 13, 2007, 09:00:14 AM »
@Cymric

I've had to do a lot of text parsing too and even then I rarely needed to concatenate strings. There are usually solutions you can come up with that don't require endless reallocation and strcat ;-)
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #27 on: February 13, 2007, 10:17:20 AM »
Quote

falemagn wrote:
@ Cymric

Why would a text parser need to concatenate strings?


My point exactly. All the parsing I've done, if anything usually involved breaking text up into smaller tokens, not concatenating them into larger ones.
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #28 on: February 13, 2007, 02:07:40 PM »
Precisely.

That's not parsing text, that's building text. String concatenation may be a viable option there, but even then there are other solutions.

Most database stuff I've had to do that wasn't from a basic LAMP/ASP perspective has all been in C++ anyway and there the basic string class has proved more than adequate for said purposes.
int p; // A
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show all replies
Re: Learning C with the Amiga
« Reply #29 from previous page: February 13, 2007, 04:43:43 PM »
@lou_dias

#include

More search/match/replace power than you can throw a very large stick at ;-)
int p; // A