Author Topic: General C programming question  (Read 8316 times)

0 Members and 1 Guest are viewing this topic.

Offline NW27Topic starter

  • Regular Contributor
  • *
  • Posts: 53
  • Country: au
General C programming question
« on: July 19, 2018, 12:43:54 pm »
Hi,
Q1. In the source file that has the main() function, is there any particular reason to have the function prototypes followed by the main() followed by the actual functions?
Why not just put the complete functions above the main and dispense with the prototypes completely?
The only thing I have encountered is that you need to be mindful of the function ordering ie called functions must be above the calling code. Otherwise I do not see any advantage.
Note - I was a pascal programmer before becoming a C programmer.

2. How many people have a header file for the main() source file and what do you use it for?

Thanks,
Neil.
 

Offline NivagSwerdna

  • Super Contributor
  • ***
  • Posts: 2495
  • Country: gb
Re: General C programming question
« Reply #1 on: July 19, 2018, 12:55:47 pm »
1. Declaring explictly is handy for clarity but also allows forward references which can be useful is a and b call each other.

2. Mostly. Putting the declarations in a header file means they can be reused elsewhere and sprinkling #ifdef to prevent issues with being #included more than once.
 

Z80

  • Guest
Re: General C programming question
« Reply #2 on: July 19, 2018, 01:03:01 pm »
Protoypes allow you to use functions before they are defined (many reasons to do this).  For a simple program with everything in order you don't need to use them (unless you are using a really old pedantic compiler).

Headers are there for global declarations.  Declare global variables, includes and function prototypes.  Again for a simple program it probably seems overkill, but when things get more complex, they are very useful.
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #3 on: July 19, 2018, 01:17:15 pm »
In a main.c file it is more readable when the first actual function is the main() itself. First digging through all the other functions is a bit PITA.
Usually a main.c file has no or very little functions, it does call lots of functions, sometimes a statemachine that kind of stuff.
Mostly for a good architecture you call the functions from other c files, the functions are defined in the header files which is the answer to your second question.   
Almost every main.c file has header files on top.

Why use other c files and header files ?
For a lot of reasons most important I can think of : clearity and re-usability.
See it like this, if you make functions you use often like helper functions or aka service / support functions, put them in a seperate support module.
You can use it each and every program you write, just include the h file and include the c file in your project.
I do this all the time, if I pick a new chip for instance a I2C clock IC or whatever I write the interface code in a seperate C file with the filename = IC name.
If i need the chip in some product I just copy the icname.c and h file in the new software, done.
I could not code without header files, you get crazy big main.c file with spaghetti code, unreadable for anyone else and totally not re-usable for the next project.

BTW this has little to do with C alone, with Pascal, C++, C#, Java just to name a few it is all the same.
 
The following users thanked this post: rs20

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #4 on: July 19, 2018, 01:33:57 pm »
Delphi has single-file units, which has two parts - interface and implementation.

In C, this typically corresponds to two files:

.h file contains everything which you would put into the "interface" section in Delphi unit.
.c file contains things which you would put into the "implementation" section.

When you want to use a compilation unit, such as

Code: [Select]
uses Something, SomethingElse;
you simply include the .h file

Code: [Select]
#include "Something.h"
#include "SomethingElse.h"

However, in C, the .h file is simply an include. You may include anything, such as a sine lookup table, for example.

Functions don't need separate declaration, but if your functions include circular calls (such as A calls B and B calls A), you will need separate declarations. This is the same as "forward" declarations in Delphi.

I don't usually have an .h file for the main.

 

Offline IonizedGears

  • Regular Contributor
  • *
  • Posts: 248
  • Country: us
Re: General C programming question
« Reply #5 on: July 19, 2018, 05:41:23 pm »
In C, scope generally extends downwards i.e. things can only see the things that are above them, not below.

Function prototypes put visibility at the top so that all of the functions within a program are aware of all of the other functions. Code structure, and more importantly, code restructuring becomes a nightmare without prototypes because you will have to order your functions so that they are below the other functions that they depend on in your program. Imagine what happens when you try to change your program. This becomes worse and worse as you add more functions so it's much better to just add prototypes than adding another headache.

Bigger programs will use header files for the prototypes so that visibility can extend to other files.

Sorry for any errors, typed this out with my phone. IX

I am an EE with interests in Embedded, RF, Control Systems, and Nanotech.
 

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2601
  • Country: us
Re: General C programming question
« Reply #6 on: July 19, 2018, 05:57:21 pm »
2. How many people have a header file for the main() source file and what do you use it for?

If you mean a "main.h" that is only included by main.c, not usually. 

Generally the point of moving declarations out of a .c file (really a compilation unit) and into a header is so you can make other compilation units aware of information or functionality that the first compilation unit provides.  So if you have a library that your application uses, your library's public interface, which is the collection of functions and variables that your application must call or access, should be declared in a header file that you include in your application's files wherever the library functionality is used.  The declarations for functions and variables used only within the library may remain in the c file if the library is simple, or for more complex multi-file libraries you might have another header file that is only included within the library. 

So because main.c canonically does not provide functionality to anything outside itself, it's not necessary to declare any of its contents to any other compilation unit.  So the only benefit to moving main.c's declarations to main.h is to hide them from main.c.  Now you might have a bunch of functions or some global variables that are used all over your application, and in that case you may well have a project-specific header that contains all of those declarations, and perhaps has its own includes for libraries that are used everywhere in the project.  However, this is a bit of a code smell, indicating that the project probably does not exhibit good encapsulation or decoupling, and it's easy to wind up with circular dependencies this way. 
 

Offline apblog

  • Regular Contributor
  • *
  • Posts: 108
  • Country: us
Re: General C programming question
« Reply #7 on: July 19, 2018, 06:11:33 pm »
It is very common to find C programs with main() at the bottom of the module, for the reason you describe. There is nothing wrong with this style.
 

Offline rhb

  • Super Contributor
  • ***
  • Posts: 3481
  • Country: us
Re: General C programming question
« Reply #8 on: July 19, 2018, 07:18:34 pm »
It is very common to find C programs with main() at the bottom of the module, for the reason you describe. There is nothing wrong with this style.

Quite agree.  And I've maintained a few million lines of other people's code.  Generally a main.h file will be used if main.c only contains main() and perhaps some functions or variables which are declared static at file scope so that they cannot be seen outside of main.c.  In large programs where main is many lines this allows interposing a debugging function between main() and another function without affecting any other files that might reference that function.  You can also produce the same result by partially linking the interposed function and the function where you want to reference it, though you may generate some warnings or encounter final link problems.  It's pretty system dependent.

Generally, once a file exceeds a few hundred lines, it's time to consider dividing it up.  And libraries should always be a single function per file unless you have functions which share a file scope global variable.  If multiple functions are declared in a single file, referencing any function from that file will include *all* the functions in the file.  This makes for considerable memory consumption at run time.
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #9 on: July 19, 2018, 08:35:55 pm »
And libraries should always be a single function per file unless you have functions which share a file scope global variable.  If multiple functions are declared in a single file, referencing any function from that file will include *all* the functions in the file.  This makes for considerable memory consumption at run time.
Really? One function per file? Are you kidding?  :palm:
 

Offline rhb

  • Super Contributor
  • ***
  • Posts: 3481
  • Country: us
Re: General C programming question
« Reply #10 on: July 19, 2018, 10:05:41 pm »
S
And libraries should always be a single function per file unless you have functions which share a file scope global variable.  If multiple functions are declared in a single file, referencing any function from that file will include *all* the functions in the file.  This makes for considerable memory consumption at run time.
Really? One function per file? Are you kidding?  :palm:

I most certainly do.  The linker doesn't include just the function you reference.  It includes the entire file.  It has to because of the scoping rules.  All those things in the language standards that most programmers never read have profound consequences for how things *must* be done.

So if someone foolishly places all the functions in a large library in one file, the system has to allocate space for the entire library to run the program.  I've had to fix this when taking over million line codebases by writing a program to break the file up into pieces.  I did it because people were unable to run the programs because they ran out of memory on $30-40K workstations.

 I'm running Hipster, the OpenSolaris derivative.  The xclock clone showing the date and time  consumes 80 MB of memory!  On Solaris 10 u8 it takes 6 MB.  I don't have a Sun 3/60 any longer, but I can assure you that xclock did not consume 30% of the16 MB memory on it.

All of this is a consequence of programmers who do not actually know what is happening at all levels when they write a line of code. I've made a lot of money fixing the mistakes engendered by their ignorance.
 

Offline NW27Topic starter

  • Regular Contributor
  • *
  • Posts: 53
  • Country: au
Re: General C programming question
« Reply #11 on: July 19, 2018, 10:20:28 pm »
Hi
Thanks for all of the responses.

I gotta say, coming from a Pascal environment (BP, Delphi & AVRCo), I'm quite disappointed by the embedded C compilers and their evolution.
Examples
1.  The compilers do not optimize out unused functions.

2. No startup/ shutdown code functions for individual source code files ie an I2C Display init unit.

3. No further development of the language for pascal style interface and implementation areas ie local global variables that can only be seen within the local source file.

The list could go on for quite a while.
There have been changes to enhance functions ie c++ but not enhancements to the not specifically IDE but to the higher level code functionality. 

Sent from my SM-N920I using Tapatalk
« Last Edit: July 19, 2018, 10:29:01 pm by NW27 »
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: General C programming question
« Reply #12 on: July 19, 2018, 10:23:48 pm »
>
Quote
libraries should always be a single function per file unless you have functions which share a file scope global variable.  If multiple functions are declared in a single file, referencing any function from that file will include *all* the functions in the file.
Or, you could use a more modern C compiler that doesn't do that.See the -ffunction-sections compiler option and -gc-sections linker option of gcc, for example.(If your compiler DOESN'T support such a feature, the single-function-per-file is good advice, assuming that the functions are distinct.  Often a high-level library won't benefit very much from such shenanigans.)
(And ...  this is a way that C++ causes code bloat.  Virtual functions ... blah blah ... will wreck havoc with they "I used that function" logic, and end up including the function from the base class whether it's ever called, or not...)  (Unless there's a magic compiler option I missed that prevents that!)
 

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 814
  • Country: se
Re: General C programming question
« Reply #13 on: July 19, 2018, 10:31:29 pm »
...ie local global variables that can only be seen within the local source file.
p
Place the variable at file scope (not inside a function) and declare it static. The variable will be seen inside functions in this file but will not be visible to other functions.
 

Offline rhb

  • Super Contributor
  • ***
  • Posts: 3481
  • Country: us
Re: General C programming question
« Reply #14 on: July 20, 2018, 01:43:08 am »
It's not the compiler.  It's ld(1) and ar(1) in a Unix environment.  I was paid very well for knowing in great detail who did what to whom.

Unfortunately, Gnu/Linux is increasingly not Unix. So I won't say what it does. They keep randomly changing option flags and everything else, just because they can.  It's *really* annoying to have a complex shell script blow up because some fool has changed the semantics of some option.  Linux is to Unix what Windows NT is to Linux.  Nice try.
 

Offline NW27Topic starter

  • Regular Contributor
  • *
  • Posts: 53
  • Country: au
Re: General C programming question
« Reply #15 on: July 20, 2018, 06:25:24 am »
It's not the compiler.  It's ld(1) and ar(1) in a Unix environment.  I was paid very well for knowing in great detail who did what to whom.

Unfortunately, Gnu/Linux is increasingly not Unix. So I won't say what it does. They keep randomly changing option flags and everything else, just because they can.  It's *really* annoying to have a complex shell script blow up because some fool has changed the semantics of some option.  Linux is to Unix what Windows NT is to Linux.  Nice try.
Sorry, I don't understand.

Sent from my SM-N920I using Tapatalk

 

Offline donotdespisethesnake

  • Super Contributor
  • ***
  • Posts: 1093
  • Country: gb
  • Embedded stuff
Re: General C programming question
« Reply #16 on: July 20, 2018, 06:33:37 am »
All of this is a consequence of programmers who do not actually know what is happening at all levels when they write a line of code.

Yes, there are a lot of those about. They are often found giving their "expert advice" on web forums.  :-DD
Bob
"All you said is just a bunch of opinions."
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #17 on: July 20, 2018, 07:41:52 am »
I most certainly do.  The linker doesn't include just the function you reference.  It includes the entire file.  It has to because of the scoping rules.  All those things in the language standards that most programmers never read have profound consequences for how things *must* be done.

So if someone foolishly places all the functions in a large library in one file, the system has to allocate space for the entire library to run the program.  I've had to fix this when taking over million line codebases by writing a program to break the file up into pieces.  I did it because people were unable to run the programs because they ran out of memory on $30-40K workstations.

 I'm running Hipster, the OpenSolaris derivative.  The xclock clone showing the date and time  consumes 80 MB of memory!  On Solaris 10 u8 it takes 6 MB.  I don't have a Sun 3/60 any longer, but I can assure you that xclock did not consume 30% of the16 MB memory on it.
I am not saying to put everything in 1 file, just all the functions that belong to a certain cluster or component otherwise you get other problems like in the next project someone will forget to include all the files.

So for instance your clock example should be a clock.c file with SetClockTime(..), GetClockTime(..) perhaps SetClockTimeZone(..), GetClockTimeZone(..) etc.
Those functions should all be included in the same component, eg c file. You are NOT going to make 4 or more seperate c files from those functions that is ludicrous and from the 6 companies I worked for over the past 20+ years I luckily never ever seen that. A C programmer that did that, would have been fired the same week.

But seperating other functionality that in your example probably was stuck in to one bloat file that consumes masses of ram, like utils or something like that,  that is also not how it should be.

Sidenote 1: modern compilers can optimize unused functions out, always check esp in embedded projects or your GUI bloat example.
Sidenote 2: self modifying Unix/Linux libraries can be a PITA since every new release you have to do it over and over again or not update which might be worse.
                  Instead you should raise a ticket with the maintainers and ask for seperation of functionality in more than one library due to exhaustive memory usage.
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: General C programming question
« Reply #18 on: July 20, 2018, 08:08:51 am »
Hi
Thanks for all of the responses.

I gotta say, coming from a Pascal environment (BP, Delphi & AVRCo), I'm quite disappointed by the embedded C compilers and their evolution.
Examples
1.  The compilers do not optimize out unused functions.

2. No startup/ shutdown code functions for individual source code files ie an I2C Display init unit.

3. No further development of the language for pascal style interface and implementation areas ie local global variables that can only be seen within the local source file.

The list could go on for quite a while.
There have been changes to enhance functions ie c++ but not enhancements to the not specifically IDE but to the higher level code functionality. 

Sent from my SM-N920I using Tapatalk
I've gotta say, coming also from a Pascal environment (but that was some 35 years ago...), that a deeper knowledge of C is needed before judging.
It takes some time and effort to switch thought patterns that have become habit.
I would not advocate one over the other (I have my own preference) but:
  • They mostly do at the link stage, see westfw post above. At compile time, unless the program is compiled as a whole, is very difficult (read: impossible) to know what will be used and what will not.
  • C leaves that to your good will and discipline. C++ has of course constructors and destructors. Standard Pascal does not have any of this, Extended (ISO10206) I think does (if you can find a compiler), the rest are proprietary extensions...
  • Scope, linkage, name space and storage duration rules are described in chapters 6.2.1, 2, 3, and 4 of the C standard. They are varied and powerful enough for most tastes, and definitely cover your example.

The list could go on for quite a while. >:D
Nandemo wa shiranai wa yo, shitteru koto dake.
 
The following users thanked this post: agehall

Offline rhb

  • Super Contributor
  • ***
  • Posts: 3481
  • Country: us
Re: General C programming question
« Reply #19 on: July 20, 2018, 01:16:44 pm »

I am not saying to put everything in 1 file, just all the functions that belong to a certain cluster or component otherwise you get other problems like in the next project someone will forget to include all the files.

So for instance your clock example should be a clock.c file with SetClockTime(..), GetClockTime(..) perhaps SetClockTimeZone(..), GetClockTimeZone(..) etc.
Those functions should all be included in the same component, eg c file. You are NOT going to make 4 or more seperate c files from those functions that is ludicrous and from the 6 companies I worked for over the past 20+ years I luckily never ever seen that. A C programmer that did that, would have been fired the same week.

But seperating other functionality that in your example probably was stuck in to one bloat file that consumes masses of ram, like utils or something like that,  that is also not how it should be.

Sidenote 1: modern compilers can optimize unused functions out, always check esp in embedded projects or your GUI bloat example.
Sidenote 2: self modifying Unix/Linux libraries can be a PITA since every new release you have to do it over and over again or not update which might be worse.
                  Instead you should raise a ticket with the maintainers and ask for seperation of functionality in more than one library due to exhaustive memory usage.

I think we're talking about software on very different scales.  For small programs it doesn't matter.   And if you're using globals with file scope they have to be in the same file.

Generally I put everything in one file for small programs.   At a certain size, I split things up into related pieces. If I want to use something in another program I put it in a library so there is only a single version to maintain.   

Having had to maintain a 500,000 line code base which had been written by copy and modify with the same bugs repeated in a dozen functions all with different names, I shudder at the idea that everything should be in one file because someone might forget to include the function.  They'll find out it's missing as soon as they try to link.  And if it's used in more than one place it belongs in a library.

Big packages like 500,000 line seismic processing systems with a dozen libraries are a whole other kettle of fish.  For things of that size you need to be very aware of how the linker operates and how the libraries are structured internally.

I think there's been considerable confusion in this discussion between the compilation and linking phases.  I'm an old VMS and Unix programmer.  I don't use Windows for programming work and I don't use IDEs for anything.  I strictly use an editor, make and the command line. 

If you're doing mixed language (C, C++ and FORTRAN)  programming you have to understand exactly how the linker works, what options are required, etc. You also need to understand the operation of the compilers at a similar level of detail.  During the workstation wars of the 80's and 90's that meant i had to know how these worked on 6 different systems for a  job porting a single package from VMS to Unix.

Seismic processing is both compute and I/O intensive.  A common operation done on all data requires in the simplest case summing at least several hundred thousand  values into each output value for many millions of output samples.  I read compiler optimization books, not because I'm going to write a compiler, but because I need to know in great detail the hardware level implications of the various optimizations.  I pay attention to cache associativity as a careless choice of memory access can flush the cache line on every access.  So in the case of a 16 byte cache and a 4 byte variable the data transfer between main memory and the cache goes up by a factor of 4x what it should be.  And the longer the cache line, the worse it gets.

I learned all this in the process of fixing problems in several million lines of other people's code.  Most of it written by scientists with few if any comments.  In one case I had to find and read a journal article just to find out whether the function was operating in the time or frequency domain.  Once I found out what it did I rewrote it.  It was probably 30-40 lines.

 I learned about the linker behavior from a set of libraries which had every function in the library in a single file.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4032
  • Country: nz
Re: General C programming question
« Reply #20 on: July 20, 2018, 01:41:50 pm »
Q1. In the source file that has the main() function, is there any particular reason to have the function prototypes followed by the main() followed by the actual functions?

I've never done this. I've maintained millions of lines of code and I don't even remember seeing it done since maybe the 1980s -- I'd say since ANSI C came out.

Except for actual .h files, I never write a prototype for a function separately from the function except to break actual mutual recursion. I take seeing a prototype internal for a file as a signal that there *is* mutual recursion involving that function prototype and the immediately following function -- and I'll expect to see the implementation right after that.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #21 on: July 20, 2018, 01:54:31 pm »
I gotta say, coming from a Pascal environment (BP, Delphi & AVRCo), I'm quite disappointed by the embedded C compilers and their evolution.

Yes, Pascal (I only used BP/Delphi) is better organized than C. If you don't use strings, but rather use C-like PChar, it can do practically the same as C, but it is more convenient than C.  It also much easier for the compiler, so your compiles get faster (old Delphi compiler can compile 300K lines in less than a second).

However, C is more universal, so often you don't have much choice but using C.

Once you get used to C quirks, it is not that much different from Pascal.

 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: General C programming question
« Reply #22 on: July 20, 2018, 02:01:10 pm »
If multiple functions are declared in a single file, referencing any function from that file will include *all* the functions in the file.  This makes for considerable memory consumption at run time.
The GNU linker will happily include just the code that's actually called (as far as it can tell) and strip away unreachable code from the binary. To do that, you have to tell the compiler (via the "-ffunction-sections") option to put each function in its own "section" and then pass the "--gc-sections" option to the linker. That's basically the standard on any microcontroller build where memory can be at a premium.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: General C programming question
« Reply #23 on: July 20, 2018, 02:12:02 pm »
[Pascal] also much easier for the compiler, so your compiles get faster (old Delphi compiler can compile 300K lines in less than a second).
I see a lot of people here talk about compile/build time, which seems surprising. This is an embedded forum, so the builds we're talking about aren't that big--it's not like you have to compile the linux kernel each time. Is the difference between a 30 second build and a 2-minute build really important? Seems like the impatience of youth, IMO.

Sure, when you're chasing that bug at 2am and on your 2nd Red Bull, that extra 90 seconds feels like an hour.  :o
 

Offline rhb

  • Super Contributor
  • ***
  • Posts: 3481
  • Country: us
Re: General C programming question
« Reply #24 on: July 20, 2018, 02:26:04 pm »
If multiple functions are declared in a single file, referencing any function from that file will include *all* the functions in the file.  This makes for considerable memory consumption at run time.
The GNU linker will happily include just the code that's actually called (as far as it can tell) and strip away unreachable code from the binary. To do that, you have to tell the compiler (via the "-ffunction-sections") option to put each function in its own "section" and then pass the "--gc-sections" option to the linker. That's basically the standard on any microcontroller build where memory can be at a premium.

Does nm(1) show you that unused functions are absent? 

The widespread use of the Gnu toolchain  for MCUs may well have resulted in the linker behavior changing.  With MCU makers funding work on the Gnu dev tools it would make sense to do that.  What actually happens when you pass those flags may be target dependent.  TI only recently started supporting the Gnu toolchain for the MSP430 with internal staff.  So I would not be at all surprised if it varied from device to device.

The only way to be sure is to look at the symbol table with nm(1) and see whether the unused  text segments are present.  There may be symbol table entries created by function prototypes, but those will go away when the symbol table is stripped.  What matters is are the text segments there.

I ran into the problem 25 years ago.  So I just adopted work habits that avoided it.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #25 on: July 20, 2018, 02:45:08 pm »
I see a lot of people here talk about compile/build time, which seems surprising. This is an embedded forum, so the builds we're talking about aren't that big--it's not like you have to compile the linux kernel each time. Is the difference between a 30 second build and a 2-minute build really important? Seems like the impatience of youth, IMO.

The difference between 2-minutes and less than a second is huge. It allows you to compile frequently, which changes your workflow and lets you be substantially more productive.

If you need to wait 2 minutes for every compile, it forces you to write more code between the compiles, and if you've got a problem, you now have to wonder which of the changes caused the bad behaviour, perhaps unroll some of your changes back, start a debugger. This all takes time and makes your work tedious. You get tired faster.

If the compile time is less than a second, you can do a single change, compile and check the result immediately. If something bad happens, you know the problem was at your last change. Of course, in the embedded, there's a programming delay and then there could be a delay with starting the test, but I always try to make such delays as short as possible.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4032
  • Country: nz
Re: General C programming question
« Reply #26 on: July 20, 2018, 03:19:01 pm »
[Pascal] also much easier for the compiler, so your compiles get faster (old Delphi compiler can compile 300K lines in less than a second).
I see a lot of people here talk about compile/build time, which seems surprising. This is an embedded forum, so the builds we're talking about aren't that big--it's not like you have to compile the linux kernel each time. Is the difference between a 30 second build and a 2-minute build really important? Seems like the impatience of youth, IMO.

Sure, when you're chasing that bug at 2am and on your 2nd Red Bull, that extra 90 seconds feels like an hour.  :o

I just read on reddit (I think) about a new programming language called Lily. I downloaded it off github and build it. It took almost exactly 1 second on my i7 NUC. I see in the makefile it's using -O2.

There are 26 C source files, totalling 23560 lines of code. Once preprocessed that expands to 90905 lines.

That's not quite the speed claimed for Delphi, but it's still bigger than most embedded projects -- the executable created has 230453 bytes in the text section.

I wasn't tooooo bored waiting for it to compile.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: General C programming question
« Reply #27 on: July 20, 2018, 03:26:21 pm »
Does nm(1) show you that unused functions are absent? 
Dunno, I never actually searched for unused functions.

Quote
With MCU makers funding work on the Gnu dev tools it would make sense to do that.  What actually happens when you pass those flags may be target dependent.
Valid point. But GCC for Cortex-M covers the majority of my projects (i.e., 100%  :)), so I haven't had to worry about portability too much. I'm interested in trying out Clang/LLVM for Cortex-M one of these days, but I think both toolchains use the same approach to dead code elimination.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: General C programming question
« Reply #28 on: July 20, 2018, 03:47:09 pm »
The difference between 2-minutes and less than a second is huge. It allows you to compile frequently, which changes your workflow and lets you be substantially more productive.
Well, lets chalk that up to differences in development style. Most of the times I compile something, it's to make sure its syntactically correct, or that the linker produces a binary--not to actually run or flash the code.

Quote
If you need to wait 2 minutes for every compile, it forces you to write more code between the compiles, and if you've got a problem, you now have to wonder which of the changes caused the bad behaviour, perhaps unroll some of your changes back, start a debugger. This all takes time and makes your work tedious. You get tired faster.
Nobody is forcing you to write more code.  I had to wait 45-minutes for a build back in the 80s, so I'd go into the machine room and practice juggling.  :-DD

https://xkcd.com/303/

Quote
If the compile time is less than a second, you can do a single change, compile and check the result immediately. If something bad happens, you know the problem was at your last change. Of course, in the embedded, there's a programming delay and then there could be a delay with starting the test, but I always try to make such delays as short as possible.
Lightning fast builds seem to be possible with IDEs and/or tiny programs, but neither of those apply to the projects I end up working on.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #29 on: July 20, 2018, 04:06:08 pm »
Nobody is forcing you to write more code.  I had to wait 45-minutes for a build back in the 80s, so I'd go into the machine room and practice juggling.  :-DD

How about you leave your deck to be run overnight and come back next day for the printout?

Lightning fast builds seem to be possible with IDEs and/or tiny programs, but neither of those apply to the projects I end up working on.

It would if you had fast Delphi-style compilers.

 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: General C programming question
« Reply #30 on: July 20, 2018, 04:19:17 pm »
How about you leave your deck to be run overnight and come back next day for the printout?
Zing!  :box:

Quote
Quote
Lightning fast builds seem to be possible with IDEs and/or tiny programs, but neither of those apply to the projects I end up working on.

It would if you had fast Delphi-style compilers.
Can I run my awk scripts from within Delphi?
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #31 on: July 20, 2018, 04:52:42 pm »
Can I run my awk scripts from within Delphi?

I'm not talking about Delphi (as IDE), just the underlying compiler.

BTW, I still use the command-line version of the Delphi compiler. I often write simple programs to generate code (tables, C code, or even Pascal code), which I use in the places where you use your awk scripts I guess. It is my "go to" compiler when I need to write something for my own use.

 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #32 on: July 20, 2018, 10:29:40 pm »
Nobody is forcing you to write more code.  I had to wait 45-minutes for a build back in the 80s, so I'd go into the machine room and practice juggling.  :-DD
I wish it was the 80s, if I do a full build it will be scheduled at night since sometimes it takes two hours to complete  :(
Luckily you don't need full builds often, just compiling your files or even the entire subcomponent takes seconds.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: General C programming question
« Reply #33 on: July 20, 2018, 10:58:11 pm »
>
Quote
Does nm(1) show you that unused functions are absent? 
yes, of course.   We're not just making this up, you know.Arduino in particular is heavily reliant on this linker/compiler feature get get rid of most of the class methods that C++ programmers love to add to their source code, which are hardly ever all used in the same sketch.
For an obvious example, compile a simple "Serial.print("Hello World");" sketch and note that the .elf file ends up with only:
WWHackintosh<10025> avr-nm -SC sketch_jul20a.ino.elf | grep Print
00000114 00000006 t Print::availableForWrite()
00000112 00000002 t Print::flush()
000000be 00000054 t Print::write(unsigned char const*, unsigned int)


In spite of Print.cpp.o being much more ... bloated:

WWHackintosh<10026> avr-nm -SC ../arduino_build_474806/core/Print.cpp.o | grep print
00000000 000001b6 T Print::printFloat(double, unsigned char)
00000000 00000092 T Print::printNumber(unsigned long, unsigned char)
00000000 00000048 T Print::print(__FlashStringHelper const*)
00000000 00000004 T Print::print(char const*)
00000000 0000001c T Print::print(String const&)
00000000 00000014 T Print::print(Printable const&)
00000000 0000000e T Print::print(char)
00000000 00000004 T Print::print(double, int)
00000000 0000000e T Print::print(unsigned char, int)
00000000 0000000e T Print::print(int, int)
00000000 0000000c T Print::print(unsigned int, int)
00000000 00000090 T Print::print(long, int)
00000000 0000001a T Print::print(unsigned long, int)
00000000 00000024 T Print::println(__FlashStringHelper const*)
00000000 00000024 T Print::println(char const*)
00000000 00000024 T Print::println(String const&)
00000000 00000024 T Print::println(Printable const&)
00000000 00000024 T Print::println(char)
00000000 00000024 T Print::println(double, int)
00000000 00000024 T Print::println(unsigned  char, int)
00000000 00000024 T Print::println(int, int)
00000000 00000024 T Print::println(unsigned int, int)
00000000 00000024 T Print::println(long, int)
00000000 00000024 T Print::println(unsigned long, int)
00000000 00000008 T Print::println()



>
Quote
What actually happens when you pass those flags may be target dependent.
No, it's pretty platform-independent.  And sort of obvious in retrospect - it just tells the compiler to generate object files in a way that makes it possible for the linker to treat individual functions as if they had come from individual .o files.   Whether existing libraries are compiled with the necessary compiler switches is another question.  AFAIK, while it's "obviously easy" for a compiler to put each function in a separate "section" (-ffunction-sections) during the compile phase, it's not possible to split up an existing .o file...

Although my impression is that outside of the embedded arena, most programs simply map in huge .dll run-time libraries with no attempt to optimize which functions are actually present.  "If it's not used, the pager will never read it in.  Maybe.  Who cares - 8GB of RAM and 64bits worth of address space!"
 
The following users thanked this post: Araho

Offline rhb

  • Super Contributor
  • ***
  • Posts: 3481
  • Country: us
Re: General C programming question
« Reply #34 on: July 21, 2018, 12:15:11 am »
Very nice to know. Thank you.   I'm glad to see that some progress is being made. Most of the time I feel as if software engineering is going backwards.

I just wish the options would be used more.  I can't run Hipster on a 2 GB dual core Atom machine because Firefox consumes all the memory to the point you can't enter text as I am doing now.  It's like being at the end of a 300 baud dialup.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: General C programming question
« Reply #35 on: July 21, 2018, 01:10:26 am »
Quote
I just wish the options would be used more.  I can't run Hipster on a 2 GB dual core Atom machine because Firefox consumes all the memory
Desktop programs are convinced that the NEED EVERY FUNCTION, and I don't think you can blame their bloat on including unused library functions.  (I'd be willing to be proven wrong, though.)
Also: VM - if firefox has vast number of unused functions, they probably wouldn't get paged in, and wouldn't cause the usage you're seeing.
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: General C programming question
« Reply #36 on: July 22, 2018, 12:40:07 pm »
Here is my "expert advice" :

Why would you type a function prototype if you dont need to type it.
So yes i organize my code that i would not need any function prototype if possible.

I only place function prototypes in main.h when they need to be called by another file.
If i need function prototypes that will only be used in main.c then i place the function prototype in main.c to make things more clear.

Main.h includes all other files from your project, and all headers include main.h, while the .c files only include theyr own header to start with.
Sometimes there are problems, i,m not sure how or what, in general it works like this with me.
aliexpress parachute
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #37 on: July 22, 2018, 03:22:34 pm »
My expert advice never ever use a main.h file, it should not exist.
Why?
Because a header file per definition is included by another file, thereby implicitly states that the belonging *.c file is a resource for another file to use.
Main.c is the highest in the hyrarchy it must and will never be included by another file, therefore it shall not have a header file and it should also not contain public functions needed by other files.
 

Offline ajb

  • Super Contributor
  • ***
  • Posts: 2601
  • Country: us
Re: General C programming question
« Reply #38 on: July 22, 2018, 05:59:46 pm »
Why would you type a function prototype if you dont need to type it.
So yes i organize my code that i would not need any function prototype if possible.

Function prototypes are inherently a violation of the DRY* principle which means they're kind of a bummer to write, but trying to structure a program to avoid them is kind of a bigger bummer.  Once you've defined a function, just copy and paste the first line of the definition to the top of the file and never worry about the order of your definitions again.  You also get a nice table of contents at the top of the file this way.  Then if you decide later on to make that function public, you can copy the prototype to an .h file. 

* Don't Repeat Yourself
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #39 on: July 22, 2018, 06:42:54 pm »
Once you've defined a function, just copy and paste the first line of the definition to the top of the file and never worry about the order of your definitions again.

My function declarations may change as I go. If I have it in two different places, I need to synchronize them - and that's a lot of worrying :) Absolutely no way I would write redundant declarations unless I have to.
 
The following users thanked this post: GeorgeOfTheJungle, JanJansen

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #40 on: July 22, 2018, 09:31:50 pm »
Once you've defined a function, just copy and paste the first line of the definition to the top of the file and never worry about the order of your definitions again.
Although this works (compiles) it is actually better IMO to not use the variable names in the declaration.
The declaration is what the compiler needs and only has to contain the function name and data types for the parameters.
The definition (implementation) is what the linker needs so only there the variable names are relevant.
It is then also easier to change you're variable names.

My function declarations may change as I go. If I have it in two different places, I need to synchronize them - and that's a lot of worrying :) Absolutely no way I would write redundant declarations unless I have to.
Let the compiler worry for you , it will throw an error on any significant difference between declaration and implementation. That is you changed data types eg from uint16 to uint32 for instance, but not if you changed the variablename of any parameter if you follow the above advice.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #41 on: July 22, 2018, 10:24:20 pm »
My function declarations may change as I go. If I have it in two different places, I need to synchronize them - and that's a lot of worrying :) Absolutely no way I would write redundant declarations unless I have to.
Let the compiler worry for you , it will throw an error on any significant difference between declaration and implementation. That is you changed data types eg from uint16 to uint32 for instance, but not if you changed the variablename of any parameter if you follow the above advice.

Compiler finding the differences, me fixing them - looks like useless work to me.
 

Offline sleemanj

  • Super Contributor
  • ***
  • Posts: 3024
  • Country: nz
  • Professional tightwad.
    • The electronics hobby components I sell.
Re: General C programming question
« Reply #42 on: July 22, 2018, 10:28:20 pm »
Although this works (compiles) it is actually better IMO to not use the variable names in the declaration.

The declaration forms part of your headers (be they in a .h file, or at the top of your .c), which can be considered documentation,

  int foo(char, char, char);

is not helpful to the developer who wants to use function foo.  If that is all that is in the header file/section, then they have to then dig through to find the implementation of this function just so they can see which order the operands are in. 

Not naming your parameters in a declaration is lazy, it costs time, and has the potential to introduce errors - subtle ones caused by a developer using foo switching operands which just happened to work out the same way in their initial testing.

If you are using declarations, make them verbose and proper, don't take short cuts, not using declarations is preferable to using lazy ones.


~~~
EEVBlog Members - get yourself 10% discount off all my electronic components for sale just use the Buy Direct links and use Coupon Code "eevblog" during checkout.  Shipping from New Zealand, international orders welcome :-)
 
The following users thanked this post: sokoloff

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #43 on: July 23, 2018, 07:05:39 am »
Agree, I am just saying it is not necessary not that from a readability point of view is recommendable.

Still if you document your function with lets say doxygen you can read the documentation for the function.
Also you can use good comments you need to go to the definition anyway.
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #44 on: July 23, 2018, 07:07:02 am »
Compiler finding the differences, me fixing them - looks like useless work to me.
From that point almost 3/4 a good SW programmer does is "useless work" untill someone else needs to take over to read or modify the code  ;)
 
The following users thanked this post: ajb

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: General C programming question
« Reply #45 on: July 23, 2018, 02:02:03 pm »
My expert advice never ever use a main.h file, it should not exist.
Why?
Because a header file per definition is included by another file, thereby implicitly states that the belonging *.c file is a resource for another file to use.
Main.c is the highest in the hyrarchy it must and will never be included by another file, therefore it shall not have a header file and it should also not contain public functions needed by other files.

The main.h you could rename to allfiles.h, it includes all files, so you only have to include main.h in your other headers.
*i am repeating myself, lets say clarify, now i stop repeating this, i hope you see the logic now.

+ i had made a game engine with many many files, you are suggesting that main.c only has a main function in it,
i learned from that mistake, i now have a few files for my latest game engine, less then 100, placing many things in 1 file, else i would have more then 100 files, i think the compiling takes also longer, + you cant have all files open at once in screen.
I cant perfectly describe how good this simple change is.
aliexpress parachute
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #46 on: July 23, 2018, 02:06:59 pm »
A compile will usually take less time when multiple files unless they all are referencing each other.
Only modified files will be recompiled at build time unless you perform a clean build ofcourse.

Sorry but I have to ask what is your experience as profesionall software engineer ?
« Last Edit: July 23, 2018, 02:14:01 pm by Kjelt »
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: General C programming question
« Reply #47 on: July 23, 2018, 02:13:54 pm »
Once you've defined a function, just copy and paste the first line of the definition to the top of the file and never worry about the order of your definitions again.

My function declarations may change as I go. If I have it in two different places, I need to synchronize them - and that's a lot of worrying :) Absolutely no way I would write redundant declarations unless I have to.

Suppose you need a function prototype i have a small tip for you when things get hectic : use a construction parameter struct to pass instead of many arguments.
aliexpress parachute
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #48 on: July 23, 2018, 02:53:42 pm »
Suppose you need a function prototype i have a small tip for you when things get hectic : use a construction parameter struct to pass instead of many arguments.

This makes things more complicated when you call a function. You either need to create a structure to pass to the function, or you need to use compound literals.

You can use a macro which contains the whole declaration, but for some reason it doesn't sit well with me.
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: General C programming question
« Reply #49 on: July 23, 2018, 03:17:24 pm »
If when you open a main.c, main() isn't the last thing at the bottom, that's a bad smell, means something fishy is going on.
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: General C programming question
« Reply #50 on: July 23, 2018, 04:10:32 pm »
This makes things more complicated when you call a function. You either need to create a structure to pass to the function, or you need to use compound literals.

You can use a macro which contains the whole declaration, but for some reason it doesn't sit well with me.

True,
i had 23 arguments in the class init + internal init + create class function ( create class & class init with overload ).
I spended so much time on the arguments, now all good.
Yes have to create the struct, only once, then can adjust.
aliexpress parachute
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: General C programming question
« Reply #51 on: July 23, 2018, 04:50:02 pm »
i had 23 arguments in the class init + internal init + create class function ( create class & class init with overload ).
I spended so much time on the arguments, now all good.
Yes have to create the struct, only once, then can adjust.

Class is already a structure. In the constructor, you initialize its variables the best you can (or not at all), then, once the class is created, you set the member variables as you please.
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: General C programming question
« Reply #52 on: July 23, 2018, 04:54:09 pm »
I do my best to set variables only once.
aliexpress parachute
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #53 on: July 23, 2018, 05:27:10 pm »
There is the culprit you are a C++ programmer.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: General C programming question
« Reply #54 on: July 23, 2018, 07:05:48 pm »
i had 23 arguments in the class init + internal init + create class function ( create class & class init with overload ).
I spended so much time on the arguments, now all good.
Yes have to create the struct, only once, then can adjust.

Class is already a structure. In the constructor, you initialize its variables the best you can (or not at all), then, once the class is created, you set the member variables as you please.
Minor nitpick...

An "instance" (or "object") is created at runtime via a C++ constructor. But a "class" is something created by the programmer.

Also, constructors are a great thing because they're a systematic way to ensure that everything is initialized. However, a good rule of thumb for embedded C++ is to avoid doing real "work" in a constructor and only set member variables to values that are constant at link-time. Compile-time constants are perfectly fine and so are addresses of things that the linker will determine. But calling code that does computation within a constructor can be risky because it's difficult to predict the initialization order of static C++ objects, and constructors of static instances are called *before* main.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: General C programming question
« Reply #55 on: July 23, 2018, 07:07:19 pm »
There is the culprit you are a C++ programmer.
Piffle. C++ is awesome for embedded work. Better than straight C, IMO.
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: General C programming question
« Reply #56 on: July 23, 2018, 08:47:30 pm »
There is the culprit you are a C++ programmer.
Piffle. C++ is awesome for embedded work. Better than straight C, IMO.
Whatever, I am not starting that endless debate again.
I was saying it since we are in a C topic  ::)
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: General C programming question
« Reply #57 on: July 24, 2018, 01:28:33 pm »
Ok the debate is on, it dont matters C or c++, you can use a struct, you can use the same trick in C, i should not have mentioned the word class to avoid debates.
aliexpress parachute
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: General C programming question
« Reply #58 on: July 24, 2018, 02:14:32 pm »
There was a C with objects, before C++.
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4032
  • Country: nz
Re: General C programming question
« Reply #59 on: July 24, 2018, 04:46:05 pm »
There was a C with objects, before C++.

Really? Which one?

Stroustrup's own "C with Classes" was started in 1979, and C++ in 1983 was a rename rather than a new language.

Cox's Objective-C was officially started in 1984 I believe. I don't know if it was unofficial before that.
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: General C programming question
« Reply #60 on: July 24, 2018, 08:02:07 pm »
Lightspeed C/Think C, it was a thing for the Mac: https://en.wikipedia.org/wiki/THINK_C
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4032
  • Country: nz
Re: General C programming question
« Reply #61 on: July 24, 2018, 09:57:59 pm »
Lightspeed C/Think C, it was a thing for the Mac: https://en.wikipedia.org/wiki/THINK_C

I used it, although I used THINK Pascal and MPW C and Pascal more. And CodeWarrior years later when the PowerPC hit.

THINK C came out in mid 1986 several years after C++ and Objective C (which both existed before the Mac was even released).
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: General C programming question
« Reply #62 on: July 25, 2018, 09:08:48 am »
THINK C came out in mid 1986 several years after C++ and Objective C (which both existed before the Mac was even released).
Existed before, but only in Stroustrup's head :-)

https://en.wikipedia.org/wiki/C++#History
Quote from: wikipedia
In 1985, the first edition of The C++ Programming Language was released, which became the definitive reference for the language, as there was not yet an official standard.[13] The first commercial implementation of C++ was released in October of the same year

The Mac's birthdate is 22, January 1984.

But yeah, my bad: in the Mac world C with objects came before C++.
« Last Edit: July 25, 2018, 04:55:24 pm by GeorgeOfTheJungle »
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4032
  • Country: nz
Re: General C programming question
« Reply #63 on: July 25, 2018, 10:36:17 am »
THINK C came out in mid 1986 several years after C++ and Objective C (which both existed before the Mac was even released).
Existed before, but only in Stroustrup's head :-)

No, cfront was available as open source software from (and used within) AT&T.

Quote
https://en.wikipedia.org/wiki/C++#History
Quote from: wikipedia
In 1985, the first edition of The C++ Programming Language was released, which became the definitive reference for the language, as there was not yet an official standard.[13] The first commercial implementation of C++ was released in October of the same year

But yeah, my bad: in the Mac world C with objects came before C++.

That first commercial implementation of C++ was Comeau C++, a supported version of cfront.

But open source, unsupported, existed before it. You could get it if you asked AT&T (or Stroustrup).

Apple's first C++ implementation in MPW was also a licensed version of cfront.
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: General C programming question
« Reply #64 on: July 25, 2018, 03:51:28 pm »
Apple's first C++ implementation in MPW was also a licensed version of cfront.

But that came later, after LightSpeed/Think C. The first MPWs did not come with any C compiler. I still have the complete docs in binders somewhere. Remember Commando? The toolbox was written in Pascal, and the calling convention was Pascal, and the strings were Pascal style, it made not much sense to use anything else in the Mac, back then.
« Last Edit: July 25, 2018, 03:54:35 pm by GeorgeOfTheJungle »
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: General C programming question
« Reply #65 on: July 25, 2018, 04:18:46 pm »
Apple's first C++ implementation in MPW was also a licensed version of cfront.

But that came later, after LightSpeed/Think C. The first MPWs did not come with any C compiler. I still have the complete docs in binders somewhere. Remember Commando? The toolbox was written in Pascal, and the calling convention was Pascal, and the strings were Pascal style, it made not much sense to use anything else in the Mac, back then.
Yep, the original AppKit for the Mac was written in Object Pascal. One of my early projects (~1990) was writing a transpiler that converted Mac-specific Object Pascal code to "portable" C++ (which was still using cfront).
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: General C programming question
« Reply #66 on: July 25, 2018, 05:54:35 pm »
I knew I had seen that name before... (you know who) now I know where: c.s.m.p !!!  8)
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4032
  • Country: nz
Re: General C programming question
« Reply #67 on: July 25, 2018, 09:52:40 pm »
Apple's first C++ implementation in MPW was also a licensed version of cfront.

But that came later, after LightSpeed/Think C.

I didn't say otherwise. MPW C++ was just mentioned as another example of using cfront, which was available in both commercial and non-commercial versions. MPW C++ was much later .. it waited for cfront 2.0.

Your claim was that THINK C (with objects) was before the first *commercial* C++. Which is true enough. But it was well after C++ was available non-commercially (on Unix).

The first C++ that wasn't based on cfront was Zortech C++ in I think late 1988 or early 1989. I probably still have the box and floppies somewhere. It was done by Walter Bright based on his earlier Lightspeed C. Symantec later bought it and ruined it. Walter of course later created D.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4032
  • Country: nz
Re: General C programming question
« Reply #68 on: July 25, 2018, 10:05:58 pm »
I knew I had seen that name before... (you know who) now I know where: c.s.m.p !!!  8)

Many years ago.

I'm amazed there are still a lot of copies of this floating around:

http://www.ralentz.com/old/mac/humor/mpw-c-errors.html

https://groups.google.com/forum/#!original/comp.sys.mac.programmer/UkCjFPL4zEM/-lM87bJxPUcJ

A slightly different list had independently been posted by Alan Rosenthal a year earlier but I think I wasn't yet on usenet at that time and BIX was still my main internet forum.
 

Offline GeorgeOfTheJungle

  • Super Contributor
  • ***
  • !
  • Posts: 2699
  • Country: tr
Re: General C programming question
« Reply #69 on: July 26, 2018, 06:39:53 pm »
The further a society drifts from truth, the more it will hate those who speak it.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: General C programming question
« Reply #70 on: July 28, 2018, 07:10:11 am »
I remember... buying a triple-threat package containing BDS C, MINCE, and Scribble.Alas, I don't think I ever used any of them: the CP/M system that they were supposed to run on never quite came together, as I over-estimated my abilities to hack both mainframes and microcomputers at the same time...
 

Offline aandrew

  • Frequent Contributor
  • **
  • Posts: 277
  • Country: ca
Re: General C programming question
« Reply #71 on: July 28, 2018, 01:50:20 pm »
So if someone foolishly places all the functions in a large library in one file, the system has to allocate space for the entire library to run the program.  I've had to fix this when taking over million line codebases by writing a program to break the file up into pieces.  I did it because people were unable to run the programs because they ran out of memory on $30-40K workstations.

This hasn't been true for quite some time now. Your experience is valid but dated.

gcc has -ffunction-sections -fdata-sections which break every function and data into separate linker sections, and then the linker option -Wl,--gc-sections which removes all unused sections. I've used this for at least the last 5 years to keep my binaries small without resorting to one-func-per-file which is a practice I abhor because it leads to the hundred-file-project which is impossible to keep in my headspace.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf