Welcome, Guest. Please login or register.

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

Description:

0 Members and 1 Guest are viewing this topic.

Offline Louis Dias

Re: Learning C with the Amiga
« Reply #74 on: February 07, 2007, 10:40:32 PM »
Hans_ wrote:
Quote

It's a quirk of the language.


It's these quirks that make it not a good language for beginners.  Maybe if she ever learns a second language (C++ doesn't count), then she'll see the light at the end of the tunnel.  C is a language with few rules.  How do you write structured code when the language has no uniform structure within it's design.  C is a language designed for low-memory machines because that's all they had when it was designed.  All these "quirks" are just hacks someone added to the compiler at the time because of memory constraints and over time "became part of the language".  C is a hack to not have to write assembly.

Quote
BTW, I think that lou_dias is wrong about arrays in structures. A fixed-length array in a structure is the data itself, not a pointer to the array. Ah, I see that Karlos has already commented on that as I was writing this.

Hans

So if the "rule" is arrays are passed by reference...why wouldn't an array within a structure not be a reference as well?  Oh, I forgot, we are talking about C...but anyway, Karlos and YOU assumed I was responding to her "code" when I was actually responding to her prior set of several questions.  I guess I should have quoted her.  C`est la vie.  (and no, that doesn't say "C is the life")
 

Offline AJCopland

Re: Learning C with the Amiga
« Reply #75 on: February 07, 2007, 10:43:41 PM »
@Karlos
For modifying things I usually manually dereference the root of a pointer hierarchy but for nested pointers I won't bother.

So for example:
(*ptr).myNestedStruct->ptrWithinStruct = NULL;

is as valid as:
ptr->myNestedStruct->ptrWithinStruct = NULL;

but... I just like it really because I see right at the start of the line what I'm doing. One of the guys I'm working with hates me doing it so I've done it less for this current project.

of course that should really have been:
assert(NULL!=ptr);
(*prt).myNestedStruct->ptrWithinStruct = NULL;
:-o
Be Positive towards the Amiga community!
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Learning C with the Amiga
« Reply #76 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 koaftder

  • Hero Member
  • *****
  • Join Date: Apr 2004
  • Posts: 2116
    • Show only replies by koaftder
    • http://koft.net
Re: Learning C with the Amiga
« Reply #77 on: February 07, 2007, 10:45:36 PM »
Only use casts whenever they are absolutely needed.

And speaking of structures and stuff, ive got a question for the gurus.

I often have things in structures that I would like to dump to file and retrieve later. I usually take the sizeof the struct and copy every byte to file, and then later read every byte and copy it into memory and refrence the struct. It is my understanding that one can only be assured of the memory location of the first member in the struct as the optimiser may pad the struct to fit in the pipeline more efficiently. This does not seem to be a problem in practice, when the application is only running on one processor type, but I think this leads to problems passing files between programs compiled on different architectures.

One obvious solution is to hit every member in the struct and write to file, then read back and repack the struct at a later time. This is kind of a pain. Is there a painless way to correctly read and write a struct to a file in a portable manner?
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Learning C with the Amiga
« Reply #78 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 AJCopland

Re: Learning C with the Amiga
« Reply #79 on: February 07, 2007, 10:56:39 PM »
@lou_dias
I've heard people describe C as a better assembler, but that doesn't make it a poor language to learn. As for imposed structure, well, I dislike imposed structure and I don't think that it teaches you to program well.

I've blown my own foot off in C more times than I'd like to imagine (C++ will let you take you're whole leg, and re-use the bullet :-D), but I think that learning how to write code so I'd avoid doing that again was a valuable lesson in itself.

You write structured code in the way that you present information, and by hiding functions in ".c" files so they only have local scope.
You preserve the intention of functions by enforcing "const" correctness, and by programming by contract. I.e. You assert that something is true at the beginning (You're input data is within ranges you expect and is valid) and that it has changed within the expected way within the function you've written at the end.

You can create libraries which hide the implementation of features you need throughout a program without giving others the ability to modify the underlying code, at least not without accessing that libraries source code directly or building their own.

Now that should teach you to structure code. By structure I mean that you'll make a conscious decision to implement things in a particular way and in a methodical manor as opposed to other languages where you implement things in a certain way... because it's the only way that the language will let you.

Andy
Be Positive towards the Amiga community!
 

Offline Louis Dias

Re: Learning C with the Amiga
« Reply #80 on: February 07, 2007, 11:13:18 PM »
@AJCopland
Quote
By structure I mean that you'll make a conscious decision to implement things in a particular way and in a methodical manor as opposed to other languages where you implement things in a certain way... because it's the only way that the language will let you.


But other languages have 1 clear way of doing every certain thing.  As long as these other languages give you all the functionality you need, why not use them with the saftey on rather than C/C++ with is playing with loaded guns and the safety(s) off.

Here we have a new student to programming and you give her the loaded gun right away.  That can/will lead to frustration.  Bad descision.  What is her "need" to learn C?  Certainly, other languages could speed up her "learning to program" process.  Learning these other languages could then speed up her subsequent "Learning To Program In C" process.
 

Offline koaftder

  • Hero Member
  • *****
  • Join Date: Apr 2004
  • Posts: 2116
    • Show only replies by koaftder
    • http://koft.net
Re: Learning C with the Amiga
« Reply #81 on: February 07, 2007, 11:18:27 PM »
@Karlos, thanks for the tips man, it's usefull for me and i'm sure it's good review for others as well. For the very few projects I do that require portability, ive hit every member in the struct and converted to network byte order and vice versa. It's a pain in the butt, especially when you have a project with a lot of different data sets. I mostly write stuff for the 8051 and use keil, which doesnt seem to do strange things with structs, but I hate my self every time I IO a struct raw....

Lately I have been messing around more with C++ on windows with MFC. I'm not a c++ guy yet but I am learning. I have seen many examples of people serializing classes to file. Especially CString classes and some of the linked list classes CList, etc. Does c++ help in serializing data in a portable manner? If i declare a class with several structs in it, will a c++ approach help make it easier to serialise to file in a portable manner?

I guess my question sounds kind of dumb, but I am wondering if doing things c++ manner can help make life easier in passing data around in files between the app compiled on different architectures. I'm not a big fan of the bloated XML libs that people bolt on to their apps. I see the usefullness of it, but XMl seems like a waste unless you need massive compatability between apps written in different languages.

 

Offline koaftder

  • Hero Member
  • *****
  • Join Date: Apr 2004
  • Posts: 2116
    • Show only replies by koaftder
    • http://koft.net
Re: Learning C with the Amiga
« Reply #82 on: February 07, 2007, 11:46:53 PM »
Quote

lou_dias wrote:

But other languages have 1 clear way of doing every certain thing.  As long as these other languages give you all the functionality you need, why not use them with the saftey on rather than C/C++ with is playing with loaded guns and the safety(s) off.


.Net framework has 100 ways to do the same thing. Which one is the best way? Ive written several apps in VB.Net, don't get me wrong, I like it. The OOP is actually nice in vb now, but still, writing to file or defining a bitmap to draw on the screen or talking with sockets have dozens of different ways to go about it. The VB and c# forums are chock full of guys bickering about the "proper" way to go about doing mundane things like every other language.

If a language was not Touring capable, it would be almost useless except for very specific things. You can do anything in VB/Perl/PHP/Python/Forth/Fortran/Befunge/Conrads game of life/ etc, but C/C++ gives the programmer the ultimate flexability to do anything with the absolute most efficency. 99 out of 100 programmers won't beat the C compiler when writing an algorithm in assembler.
 

Offline Sys_64738

  • Newbie
  • *
  • Join Date: Jan 2007
  • Posts: 3
    • Show only replies by Sys_64738
Re: Learning C with the Amiga
« Reply #83 on: February 08, 2007, 12:00:46 AM »
@koaftder:

Regard MFC serialization, it is the *framework* (MFC framework) that helps you in serialization work, providing a pre-built infrastructure for serialization.

So you can simply add a Serialize() virtual method to your custom class (deriving it from CObject), and simply use operators << and >> for serialization.

This can be done recursively, also for classes containing structures, and for structures containing nested structures, etc.
(The important thing is that the object is "serializable", i.e. it must provide a Serialize() method, etc.)

This is not possible in C because C does not offer operator-overloading and virtual functions and polymorphism and late-binding at the level of C++ (even if these things may be done also in C, but at the expense of writing more code).

However, C++ has not built-in serialization mechanism. It is the framework you use (e.g. MFC) that can provide one (and if you follow the framework rules, you can have serialization for your own classes fairly simply).

Maybe C++ Boost libraries offer another serialization mechanism (more standard than the MFC-specific one).

 

Offline CannonFodder

  • Hero Member
  • *****
  • Join Date: Sep 2003
  • Posts: 1115
    • Show only replies by CannonFodder
Re: Learning C with the Amiga
« Reply #84 on: February 08, 2007, 12:09:49 AM »
Quote
C is a language designed for low-memory machines because that's all they had when it was designed.


That´s not strictly true Lou, C is a language designed for control freaks.

[Purely my opinion]
Programmers that are not control freaks, are not very good programmers.
[/Purely my opinion]

ps I use a RAD tool you will never have heard of, and it is far more abstracted than VB.NET even.  I love it, and very rarely use anything else for commercial work but I still say C is God´s own language. ;-)

C++ is just a ¨bida¨ Karlos! :-P
People are hostile to what they do not understand - Imam Ali ibn Abi Talib(AS)
 

Offline Karlos

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16879
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: Learning C with the Amiga
« Reply #85 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 only replies by Karlos
Re: Learning C with the Amiga
« Reply #86 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 only replies by Karlos
Re: Learning C with the Amiga
« Reply #87 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 CannonFodder

  • Hero Member
  • *****
  • Join Date: Sep 2003
  • Posts: 1115
    • Show only replies by CannonFodder
Re: Learning C with the Amiga
« Reply #88 on: February 08, 2007, 12:33:54 AM »
Quote

Karlos wrote:
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.


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


/me runs very very fast!!
People are hostile to what they do not understand - Imam Ali ibn Abi Talib(AS)
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show only replies by Piru
    • http://www.iki.fi/sintonen/
Re: Learning C with the Amiga
« Reply #89 from previous page: February 08, 2007, 08:30:23 AM »
@AJCopland
Quote
Now that should teach you to structure code. By structure I mean that you'll make a conscious decision to implement things in a particular way and in a methodical manor as opposed to other languages where you implement things in a certain way... because it's the only way that the language will let you.

Amen to that (and the rest of the message). Well put.