Softpanorama

May the source be with you, but remember the KISS principle ;-)
Contents Bulletin Scripting in shell and Perl Network troubleshooting History Humor

Softpanorama C Language Webliography

Old News ;-) See also Books
Reviews
Recommended Links Articles Tutorials University courses References
FAQs Pointers and arrays Standard Library I/O  Control Structures Subroutines Strings  
Coroutines in C Unix system calls Code Examples Optimization of code Lint Debugging Programming Style Unix programming
Typical Errors Prettyprinting HTMlLsers   History Random Findings Humor Etc

Dr. Nikolai Bezroukov

Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

2004 2003 2002 2001 2000

V IDE

V IDE works with GNU g++, Borland C++ 5.5 and Java and runs on Windows and Linux. It includes a syntax highlighting editor for C/C++, Java, Perl, Fortran, TeX and HTML. It has a built-in code beautifier, macro support, ctags support, project manager, integrated support for the V applications generator and icon editor, integrated support for the GNU gdb and Sun's jdb (for Java), etc.

Slashdot Optimizations - Programmer vs. Compiler

Re:Clear Code (Score:5, Insightful)
by Rei (128717) on Friday February 25, @04:56PM (#11782241)
(http://www.cursor.org/)

An important lesson that I wish I had learned when I was younger < cite>;) It is crazy to start optimizing before you know where your bottlenecks are. Don't guess - run a profiler. It's not hard, and you'll likely get some big surprises.

Another thing to remember is this: the compiler isn't stupid; don't pretend that it is. I had senior developers at an earlier job mad at me because I wasn't creating temporary variables for the limits of my loop indices (on unprofiled code, nonetheless!). It took actually digging up an article on the net to show that all modern compilers automatically dereference any const references (be they arrays, linked lists, const object functions, etc) before starting the loop.

Another example: function calls. I've heard some people be insistant that the way to speed up an inner loop is to remove the code from function calls so that you don't have function call overhead. No! Again, compilers will do this for you. As compilers were evolving, they added the "inline" keyword, which does this for you. Eventually, the compilers got smart enough that they started inlining code on their own when not specified and not inlining it when coders told it to be inline if it would be inefficient. Due to coder pressure, at least one compiler that I read about had an "inlinedamnit" (or something to that effect) keyword to force inlining when you're positive that you know better than the compiler ;)

Once again, the compiler isn't stupid. If an optimization seems "obvious" to you, odds are pretty good that the compiler will take care of it. Go for the non-obvious optimizations. Can you remove a loop from a nested set of loops by changing how you're representing your data? Can you replace a hack that you made with standard library code (which tends to be optimized like crazy)? Etc. Don't start dereferencing variables, removing the code from function calls, or things like this. The compiler will do this for you.

If possible, work with the compiler to help it. Use "restrict". Use "const". Give it whatever clues you can.

Time to post the famous Knuth quote... (Score:5, Informative)
by xlv (125699) on Friday February 25, @03:50PM (#11781223)
(http://dumbasastone.com/ | Last Journal: Thursday September 23, @10:06PM)

Donald Knuth wrote "We should forget about small efficiencies, about 97% of the time. Premature optimization is the root of all evil."

Write C for C programmers (Score:5, Insightful)
by swillden (191260) * on Friday February 25, @03:55PM (#11781306)

With regard to your example, I can't imagine any modern compiler wouldn't treat the two as equivalent.

However, in your example, I actually prefer "if (!ptr)" to "if (ptr == NULL)", for two reasons. First the latter is more error-prone, because you can accidentally end up with "if (ptr = NULL)". One common solution to avoid that problem is to write "if (NULL == ptr)", but that just doesn't read well to me. Another is to turn on warnings, and let your compiler point out code like that -- but that assumes a decent compiler.

The second, and more important, reason is that to anyone who's been writing C for a while, the compact representation is actually clearer because it's an instantly-recognizable idiom. To me, parsing the "ptr == NULL" format requires a few microseconds of thought to figure out what you're doing. "!ptr" requires none. There are a number of common idioms in C that are strange-looking at first, but soon become just another part of your programming vocabulary. IMO, if you're writing code in a given language, you should write it in the style that is most comfortable to other programmers in that language. I think proper use of idiomatic expressions *enhances* maintainability. Don't try to write Pascal in C, or Java in C++, or COBOL in, well, anything, but that's a separate issue < cite> :-)

Oh, and my answer to your more general question about whether or not you should try to write code that is easy for the compiler... no. Don't do that. Write code that is clear and readable to programmers and let the compiler do what it does. If profiling shows that a particular piece of code is too slow, then figure out how to optimize it, whether by tailoring the code, dropping down to assembler, or whatever. But not before.

Check out the LLVM demo page (Score:5, Interesting)
by sabre (79070) on Friday February 25, @03:58PM (#11781354)
(http://www.nondot.org/~sabre/)

LLVM is an aggressive compiler that is able to do many cool things. Best yet, it has a demo page here: http://llvm.org/demo [llvm.org], where you can try two different things and see how they compile.

One of the nice things about this is that the code is printed in a simple abstract assembly language that is easy to read and understand.

The compiler itself is very cool too btw, check it out. < cite> :)

If you're not willing to TIME it... (Score:4, Insightful)
by dpbsmith (263124) on Friday February 25, @04:30PM (#11781872)
(http://world.std.com/~dpbsmith) ...then the code isn't important enough to optimize. Plain and simple.

Never try to optimize anything unless you have measured the speed of the code before optimizing and have measured it again after optimizing.

Optimized code is almost always harder to understand, contains more possible code paths, and more likely to contain bugs than the most straightforward code. It's only worth it if it's really faster...

And you simply cannot tell whether it's faster unless you actually time it. It's absolutely mindboggling how often a change you are certain will speed up the code has no effect, or a truly negligible effect, or slows it down.

This has always been true. In these days of heavily optimized compilers and complex CPUs that are doing branch prediction and God knows what all, it is truer than ever. You cannot tell whether code is fast just by glancing at it. Well, maybe there are processor gurus who can accurately visualize the exact flow of all the bits through the pipeline, but I'm certainly not one of them.

A corollary is that since the optimized code is almost always trickier, harder to understand, and often contains more logic paths than the most straightforward code, you shouldn't optimize unless you are committed to spending the time to write a careful unit-test fixture that exercises everything tricky you've done, and write good comments in the code.

Premature Optimization (Score:5, Insightful)
by fizban (58094) <fizban@umich.edu> on Friday February 25, @05:06PM (#11782376)
(http://www.sophicstudios.com/)

Premature Optimization is the DEVIL! I repeat, it is the gosh darn DEVIL! Don't do it. Write clear code so that I don't have to spend days trying to figure out what you are trying to do.

The biggest mistake I see in my professional (and unprofessional) life is programmers who try to optimize their code is all sorts of "733+" ways, trying to "trick" the compiler into removing 1 or 2 lines of assembly, yet completely disregard that they are using a map instead of a hash_map, or doing a linear search when they could do a binary search, or doing the same lookup multiple times, when they could do it just once. It's just silly, and goes to show that lots of programmers don't know how to optimize effectively.

Compilers are good. They optimize code well. Don't try to help them out unless you know your code has a definite bottleneck in a tight loop that needs hand tuning. Focus on using correct algorithms and designing your code from a high level to process data efficiently. Write your code in a clear and easy to read manner, so that you or some other programmer can easily figure out what's going on a few months down the line when you need to add fixes or new functionality. These are the ways to build efficient and maintainable systems, not by writing stuff that you could enter in an obfuscated code contest.

valgrind (Score:4, Informative)
by cyco/mico (178541) on Friday February 25, @05:12PM (#11782431)

If in doubt, use valgrind and kcachegrind [sourceforge.net]. One run with callgrind gives you all the information you want:

callgrind/kcachegrind is by far the easiest profiling solution I ever tried, and it seems answer more or less all of your questions.

Rules for writing fast code (aka optimization) (Score:4, Insightful)
by MSBob (307239) on Friday February 25, @05:56PM (#11782860)

First: Avoid doing what you don't have to do. Sounds obvious but I rarely see code that does the absolute minimum it needs to. Most of the code I've seen to date seems to precalculate too much stuff, read too much data from external storage, redraw too much stuff on screen etc...

Second: Do it later. There are thousands of situations where you can postpone the actual computations. Imagine writing a Matrix class with the invert() method. You can actually postpone calculating the inverse of the matrix until there is a call to access on of the fields in the matrix. Also you can calculate only the field being accessed. Or at some sensible threshold you may assume that the user code will read the entire inverted matrix and you can just calculate the remaining inverted fields... the options are endless.


Most string class implementations already make good use of this rule by only copying their buffers only when the "copied" buffer changes.

Third: Apply minimum algorithmic complexity. If you can use a hashmap instead of a treemap use the hash version it's O(1) vs Olog(n). Use quicksort for just about any kind of sorting you need to do.

Fourth: Cache your data. Download or buy a good caching class or use some facilities your language provides (eg. Java SoftReference class) for basic caching. There are some enormous performance gains that can be realized with smart caching strategies.

Fifth: Optimize using your language constructs. User the register keyword, use language idioms that you know compile into faster code etc... Scratch this rule! If you're applying rules one to four you can forget about this one and still have fast AND readable code.

The never overused example that I have (Score:4, Informative)
by roman_mir (125474) on Friday February 25, @05:56PM (#11782867)
(http://slashdot.org/ | Last Journal: Monday December 08, @11:44AM)

I got this job as a contractor 4 years ago now where the project was developed by over 30 junior developers and one crazy overpaid lady (hey, Julia,) who wouldn't let people touch her code so fragile it was (and it was the main action executor,) she would rather fight you for hours than make one change in the code (she left 2 months before the project release.) Now, I have never witnessed such monstrocity of a code base before - the business rules were redefined about once every 2 weeks dor 1.5 years straight. You can imagine.

So, the client decided not to pay the last million of dollars because the performance was total shit. On a weblogic cluster of 2 Sun E45s they could only achieve 12 concurrent transactions per second. So the client decided they really did not want to pay and asked us to make it at least 200 concurrent transactions per second on the same hardware. If I may make a wild guess, I would say the client really did not want to pay the last million, no matter what, so they upped the numbers a bit from what they needed. But anyway.

Myself and another developer (hi, Paul) spent 1.5 months - removing unnecessary db calls (the app was incremental, every page would ask you more questions that needed to be stored, but the app would store all questions from all pages every time,) cached XML DOM trees instead of reparsing them on every request, removed most of the session object, reduced it from 1Mb to about 8Kb, removed some totally unnecessary and bizarre code (the app still worked,) desynchronized some of the calls with a message queue etc.

At the end the app was doing 320 and over concurrent transactions per second. The company got their last million.

The lesson? Build software that is really unoptimized first and then save everyone's ass by optimizing this piece of shit and earn total admiration of the management - you are a miracle worker now.

The reality? Don't bother trying to optimize code when the business requirements are constantly changing, the management has no idea how to manage an IT dep't, the coders are so nube - there is a scent of freshness in the air and there is a crazy deadline right in front of you. Don't optimize, if the performance becomes an issue, optimize then.

Highlight UnMatched Brackets - Capture those unmatched brackets while u r still in insert-mode vim online

Its really irksome when your compiler complains for any unmatched "{" or "(" or "[". With this plugin you can highlight all those unmatched "{" or "(" or "[" as you type. This helps you to keep track of where the exact closing bracket should come. This plugin also warns you of any extra "}" or ")" or "]" you typed.

Customization:
- Specifying Additional Bracket-pairs.
User can specify additional matching pairs in
the global option 'matchpairs', see :help 'matchpairs'
For eg: set mps+=<:> (to include <> pair)
put the above setting in .vimrc file and restart vim.
- To get rid of highlighting when you quit insert
mode, add this mapping in your vimrc
noremap! <Esc> <Esc>:match NONE<CR>

To test how this plugin works type something like
{
( ) [ ]
( ( ( ) ) )
}

Happy vimming.

ShowFunc.vim - Creates a list of all tags - functions from a window, all windows or buffers. vim online

This script creates a hyperlink list of all the tags (i.e. functions, subroutines, classes, macros or procedures) from a single buffer, all open windows or buffers and displays them in a dynamically sized cwindow.

Supported File types with Exuberant Ctags version 5.5.4 (and newer): Asm, Asp, Awk, Beta, C, C++, c#, Cobol, Eiffel, Erlang, Fortran, Java, Javascript, Lisp, Lua, Make, Pascal, Perl, PHP, Python, PL/SQL, REXX, Ruby, Scheme, Shell, SLang, SML, SQL, Tcl, Vera, Verilog, Vim, YACC......and any user defined (i.e. --regex-lang=) types.

Default Key Mappings:
<F1> Run scan and open cwindow.

To reassign add the following to your .vimrc:
map NewKey <Plug>ShowFunc
map! NewKey <Plug>ShowFunc
For example to change the <F1> mapping to <F7>
map <F7> <Plug>ShowFunc
map! <F7> <Plug>ShowFunc

ShowFunc Window commands:
c Close cwindow.
h Display help dialog.
r Refresh.
s Change file sort, results will appear in either alphabetical or file order. (Default: file order)
t Change scan type, results will be from either the current file, all open windows or all open buffers. (Default: all open buffers) install details Put this file in the vim plugins directory (~/.vim/plugin/) to load it automatically, or load it with :so ShowFunc.vim.

You need Exuberant CTags installed for this function to work.
Website: http://ctags.sourceforge.net/
Source: http://prdownloads.sourceforge.net/ctags/ctags-5.5.4.tar.gz
Redhat/Fedora RPM: http://prdownloads.sourceforge.net/ctags/ctags-5.5.4-1.i386.rpm
Debian: apt-get install exuberant-ctags

vimcommander - totalcommander-like two-panel tree file explorer for vim vim online

This is an adaptation of opsplorer (vimscript #362), intended to be more like the Total Commander (http://www.ghisler.com) file explorer.

This opens two panels of file explorers on the top half of the vim screen.
Targets for moving and copying defaults to the other panel, like totalcmd. TAB switches between panels.
Vimcommander keys are mostly totalcommander's:
F3 - view
F4 - edit
F5 - copy
F6 - move
F7 - create dir
F8 - del
Others: C-U, C-Left/C-Right, C-R, BS, DEL, C-H, etc.
Selection of files/dirs also works: INS, +, -. Then copy/move/del selected files.

Suggested binding is noremap <silent> <F11> :cal VimCommanderToggle()<CR>
install details Drop vimcommander.vim in ~/.vim/plugin
Put in you .vimrc a map to VimCommanderToggle():
noremap <silent> <F11> :cal VimCommanderToggle()<CR>

c.vim - Write C-C++ programs by inserting statements, idioms and comments. vim online

** Statement oriented editing of C / C++ programs
** Speed up writing new code considerably.
** Write code und comments with a professional appearance from the beginning.
** Use code snippets

- insertion of various types of comments (file prologue, function descriptions, file section headers
keyword comments, date, time, ... )
- insertion of empty control statements (if-else, while, do-while, switch, ... )
- insertion of various preprocessor directives
- insertion of C-idioms (enum+typedef, loops, complete main, empty function, file open dialogs, ... )
- insertion of C++ -idioms ( frames for simple classes and template classes, try-catch blocks,
file open dialogs, output manipulators, ios flags, ... )
- compile / link / run support for one-file projects (without a makefile)
- personalization of comments (name, email, ... )
- menus can be switched on and off (Tools menu)

[Jan 2, 2005] CRefVim - a C-reference manual especially designed for Vim vim online

The intention of this project is to provide a C-reference manual that can be viewed with Vim and accessed from within Vim. The C-reference is a reference, it is NOT a tutorial or a guide on how
to write C-programs. It is a quick reference to the functions and syntax of the standard C language.

[Jan 2, 2005] C-fold - Automates folding and unfolding C & C++ comments and code blocks. vim online

Automatically folds all blocks (i.e. { } ) in C and C++ and defines a function that performs a command e.g. zo on all folds beginning with text that matches a given pattern.

This allows for the following mappings defined by the plugin:

z[ - Opens all doxygen-style comments
z] - Closes all doxygen-style comments
z{ - Opens all code blocks (i.e. { })
z} - Closes all code blocks install details Extract the archive from your home directory. This will extract the following files:
.vim/plugins/cfold.vim
.vim/after/syntax/c.vim

Also requires the folding of Doxygen-style comments. This requires vimscript #5. This can be done easily by adding the 'fold' keyword to the end of the 'doxygenComment' region in the 'doxygen.vim' syntax file:

syn region doxygenComment start= ... keepend fold

Additional languages can be supported as appropriate (e.g. Java) by copying 'c.vim' and renaming to the syntax file for the language (e.g. java.vim).

The Linux Tips HOWTO Short Tips

Linux Online

I do a lot of C programming in my spare time, and I've taken the time to rig vi to be C friendly. Here's my .exrc:

set autoindent
set shiftwidth=4
set backspace=2
set ruler

What does this do? autoindent causes vi to automatically indent each line following the first one indented, shiftwidth sets the distance of ^T to 4 spaces, backspace sets the backspace mode, and ruler makes it display the line number. Remember, to go to a specific line number, say 20, use:

vi +20 myfile.c

Using ctags to ease programming.

Most hackers already have ctags on their computers, but don't use it. It can be very handy for editing specific functions. Suppose you have a function, in one of many source files in a directory for a program you're writing, and you want to edit this function for updates. We'll call this function foo(). You don't where it is in the source file, either. This is where ctags comes in handy. When run, ctags produces a file named tags in the current dir, which is a listing of all the functions, which files they're in and where they are in said files. The tags file looks like this:

ActiveIconManager       iconmgr.c       /^void ActiveIconManager(active)$/
AddDefaultBindings      add_window.c    /^AddDefaultBindings ()$/
AddEndResize    resize.c        /^AddEndResize(tmp_win)$/
AddFuncButton   menus.c /^Bool AddFuncButton (num, cont, mods, func, menu, item)$/
AddFuncKey      menus.c /^Bool AddFuncKey (name, cont, mods, func, menu, win_name, action)$/
AddIconManager  iconmgr.c       /^WList *AddIconManager(tmp_win)$/
AddIconRegion   icons.c /^AddIconRegion(geom, grav1, grav2, stepx, stepy)$/
AddStartResize  resize.c        /^AddStartResize(tmp_win, x, y, w, h)$/
AddToClientsList        workmgr.c       /^void AddToClientsList (workspace, client)$/
AddToList       list.c  /^AddToList(list_head, name, ptr)$/

To edit, say AddEndResize() in vim, run:

vim -t AddEndResize
This will bring the appropriate file up in the editor, with the cursor located at the beginning of the function.

[Jan 2, 2005] C-editing-with-VIM-HOWTO. See also Ctags code browsing framework

3.1. ctags

A Tag is a sort of placeholder. Tags are very useful in understanding and
editing C. Tags are a set of book-marks to each function in a C file. Tags
are very useful in jumping to the definition of a function from where it is
called and then jumping back.

Take the following example.


Figure 6. Tags Example

[tags]

Lets say that you are editing the function foo() and you come across the
function bar(). Now, to see what bar() does, one makes uses of Tags. One can
jump to the definition of bar() and then jump back later. If need be, one can
jump to another function called within bar() and back.

To use Tags one must first run the program ctags on all the source files.
This creates a file called tags. This file contains pointers to all the
function definitions and is used by VIM to take you to the function
definition.

The actual keystrokes for jumping to and fro are CTRL-] and CTRL-T. By
hitting CTRL-] in foo() at the place where bar() is called, takes the cursor
to the beginning of bar(). One can jump back from bar() to foo() by just
hitting CTRL-T.

ctags are called by
$ ctags options file(s)

To make a tags file from all the *.c files in the current directory all one
needs to say is
$ ctags *.c

In case of a source tree which contains C files in different sub directories,
one can call ctags in the root directory of the source tree with the -R
option and a tags file containing Tags to all functions in the source tree
will be created. For Example.
$ ctags -R *.c

There are many other options to use with ctags. These options are explained
in the man file for ctags.
-----------------------------------------------------------------------------

3.2. marks

Marks are place-holders like Tags. However, marks can be set at any point in
a file and is not limited to only functions, enums etc.. Plus marks have be
set manually by the user.

By setting a mark there is no visible indication of the same. A mark is just
a position in a file which is remembered by VIM. Consider the following code


Figure 7. The marks example

[marks]

Suppose you are editing the line x++; and you want to come back to that line
after editing some other line. You can set a mark on that line with the
keystroke m' and come back to the same line later by hitting ''.

VIM allows you to set more than one mark. These marks are stored in registers
a-z, A-Z and 1-0. To set a mark and store the same in a register say j, all
one has to hit is mj. To go back to the mark one has to hit 'j.

Multiple marks are really useful in going back and fro within a piece of
code. Taking the same example, one might want one mark at x++; and another at
y=x; and jump between them or to any other place and then jump back.

Marks can span across files. To use such marks one has to use upper-case
registers i.e. A-Z. Lower-case registers are used only within files and do
not span files. That's to say, if you were to set a mark in a file foo.c in
register "a" and then move to another file and hit 'a, the cursor will not
jump back to the previous location. If you want a mark which will take you to
a different file then you will need to use an upper-case register. For
example, use mA instead of ma. I'll talk about editing multiple files in a
later section.
-----------------------------------------------------------------------------

3.3. gd keystroke

Consider the following piece of code.


Figure 8. The third example

[gd]

For some reason you've forgotten what y and z are and want to go to their
declaration double quick. One way of doing this is by searching backwards for
y or z. VIM offers a simpler and quicker solution. The gd keystroke stands
for Goto Declaration. With the cursor on "y" if you hit gd the cursor will
take you to the declaration :- struct Y y;.

A similar keystroke is gD. This takes you to the global declaration of the
variable under the cursor. So if one want to go to the declaration of x, then
all one needs to do is hit gD and the cursor will move to the declaration of
x.

[Dec 26, 2004] Writing a C-based Client-Server

Consider for a moment having the massive power of different computers all simultaneously trying to compute a problem for you—and still being legal! With the commonplace interconnectivity that a network brings, you can do just that. All you need is a login and a compiler—and a few system calls.

Network programming extends the ability to solve computational problems. Nearly all network programs use sockets to provide connection points between the source and destination. You can compare sockets with an in/out box for messages between tasks on different computers. All you need is a host address and port, and you can send and receive messages from anywhere on your network.

See also

[Nov 12, 2004] C Coroutines

co_create, co_call, co_resume, co_delete, co_exit_to, co_exit - C coroutine management

The coro library implements the low level functionality for coroutines. For a definition of the term coroutine see The Art of Computer Programming by Donald E. Knuth. In short, you may think of coroutines as a very simple cooperative multitasking environment where the switch from one task to another is done explicitly by a function call. And, coroutines are fast. Switching from one coroutine to another takes only a couple of assembler instructions more than a normal function call.

This document defines an API for the low level handling of coroutines i.e. creating and deleting coroutines and switching between them. Higher level functionality (scheduler, etc.) is not covered.

[Oct 28, 2004] Open source compiler demos speed, compactness with boottime compile trick

A project to build a C compiler small enough to enable C to be used as a scripting language has released an impressive technology demonstration: a bootloader that uses the Tiny C Compiler (TCC) to compile a Linux kernel from source at boot-time in as little as 15 seconds.

TCCBoot is framed on creator Fabrice Bellard's website as a demonstration application for Bellard's Tiny C Compiler (TCC), described as "a tiny but complete ISOC99 C compiler which enables you to use C as scripting language." According to Bellard, TCC is several times faster than gcc, produces optimized code, and is small enough "(about 100KB for x86 TCC executable, including C preprocessor, C compiler, assembler and linker)" to be used on rescue disks, among other features.

TCCBoot is distributed as an ISO image, as well as source code. The ISO image can be burned onto a CD and used to boot x86 PCs. The CD first loads an initrd filesystem on which kernel C and assembly code have been stashed in a gzipped ROMFS. It then reads a TCC config file before compiling a binary kernel image. the image is then booted, leaving the user in a rudimentary Linux environment featuring a very basic shell with benchmarking software.

We couldn't resist trying it. The whole boot process took about 45 seconds, including 33 seconds of compile time, on a 1.6GHz Pentium M.

Project creator Fabrice Bellard writes, "It is sure that there are still many bugs in the kernel generated by TinyCC/TCCBOOT, but at least it can boot and launch a shell."

Among Bellard's other accomplishments are a victory in a 1997 "obfuscated C" programming contest, and the creation of the "most efficient formula to date to compute the nth binary digits of Pi." Bellard also made significant contributions to a project to create GPL support for Memory Technology Devices (MTD) DiskOnChip technology.

More details about TCC, TCCBoot and Bellard's other interesting projects are available on his website.

[Sept 10, 2004] http://www.digitalmars.com/

Digital Mars C and C++ Compilers for Win32, Win16, DOS32 and DOS. Fastest compile/link times, powerful optimization technology, Design by Contract, complete library source, HTML browsable documentation, disassembler, librarian, resource compiler, make, etc., command line and GUI versions, tutorials, sample code, online updates, Standard Template Library, and much more!

[ Mar 24 2004] Open source development using C99

Is your C code up to standard? by Peter Seebach (developerworks@seebs.plethora.net) What is C99? Who needs it? Is it available yet? Peter Seebach discusses the 1999 revision of the ISO C standard, with a focus on the availability of new features on Linux and BSD systems.

... ... ...
There are two parts of the C programming language. These are, confusingly, called the "language" and the "library." Historically, there was a bundle of commonly used utility code that everyone tended to reuse; this was eventually standardized into what's called the Standard C Library. The distinction was pretty easy to understand at first: If the compiler did it, it was the language; if it was in the add-on code, it was the library.

With time, however, the distinction has been blurred. For instance, some compilers will generate calls to an external library for 64-bit arithmetic, and some library functions might be handled magically by the compiler. For the purposes of this article, the division follows the terminology of the standard: features from the "Library" section of the standard are library features and are discussed in the next section of the article. This section looks at everything else.

The C99 language introduces a number of new features that are of potential interest to software developers. Many of these features are similar to features of the GNU C set of extensions to C; unfortunately, in some cases, they are not quite compatible.

A few features popularized by C++ have made it in. In particular, // comments and mixed declarations and code have become standard features of C99. These have been in GNU C forever and should work on every platform. In general, though, C and C++ remain separate languages; indeed, C99 is a little less compatible with C++ than C89 was. As always, trying to write hybrid code is a bad idea. Good C code will be bad C++ code.

C99 added some support for Unicode characters, both within string literals and in identifiers. In practice, the system support for this probably isn't where it needs to be for most users; don't expect source that uses this to be accessible to other people just yet. In general, the wide character and unicode support is mostly there in the compiler, but the text processing tools aren't quite up to par yet.

The new variable-length array (VLA) feature is partially available. Simple VLAs will work. However, this is a pure coincidence; in fact, GNU C has its own variable-length array support. As a result, while simple code using variable-length arrays will work, a lot of code will run into the differences between the older GNU C support for VLAs and the C99 definition. Declare arrays whose length is a local variable, but don't try to go much further.

Compound literals and designated initializers are a wonderful code maintainability feature. Compare these two code fragments:

Listing 1. Delaying for n microseconds in C89


    /* C89 */
    {
        struct timeval tv = { 0, n };
        select(0, 0, 0, 0, &tv);
    }

Listing 2. Delaying for n microseconds in C99


    // C99
    select(0, 0, 0, 0, & (struct timeval) { .tv_usec = n });

The syntax for a compound literal allows a brace-enclosed series of values to be used to initialize an automatic object of the appropriate type. The object is reinitialized each time its declaration is reached, so it's safe with functions (such as some versions of select) that may modify the corresponding object. The designated initializer syntax allows you to initialize members by name, without regard to the order in which they appear in an object. This is especially useful for large and complicated objects with only a few members initialized. As with a normal aggregate initializer, missing values are treated as though they'd been given 0 as an initializer. Other initialization rules have changed a bit. For instance, you're now allowed to have a trailing comma after the last member of an enum declaration, to make it just a bit easier to write code generators.

For years, people have been debating extensions to the C type system, such as long long. C99 introduces a handful of new integer types. The most widely used is long long. Another type introduced by the standards process is intmax_t. Both of these types are available in gcc. However, the integer promotion rules are not always correct for types larger than long. It's probably best to use explicit casts.

There are also a lot of types allowing more specific descriptions of desired qualities. For instance, there are types with names like int_least8_t, which has at least 8 bits, and int32_t, which has exactly 32 bits. The standard guarantees access to types of at least 8, 16, 32, and 64 bits. There is no promise that any exact-width types will be provided. Don't use such types unless you are really, totally sure that you can't accept a larger type. Another optional type is the new intptr_t type, which is an integer large enough to hold a pointer. Not all systems provide such a type (although all current Linux and BSD implementations do).

The C preprocessor has a number of new features. It allows empty arguments, and it supports macros with varying numbers of arguments. There is a _Pragma operator for macro-generating pragmas, and there's a __func__ macro, which always contains the name of the current function. These features are available in current versions of gcc.

C99 added the inline keyword to suggest function inlining. GNU C also supports this keyword, but with slightly different semantics. If you're using gcc, you should always use the static keyword on inline functions if you want the same behavior as C99 would give for the code. This may be addressed in future revisions; in the meantime, you can use inline as a compiler hint, but don't depend on the exact semantics.

C99 introduced a qualifier, restrict, which can give a compiler optimization hints about pointers. Because there is no requirement that a compiler do anything with this, it's done in that gcc accepts it. The degree of optimization done varies. It's safe to use, but don't count on it making a huge difference yet. On a related note, the new type-aliasing rules are fully supported in gcc. This mostly means that you must be more careful about type punning, which is almost always going to invoke undefined behavior, unless the type you're using to access data of the wrong sort is unsigned char.

Array declarators as function arguments now have a meaningful difference from pointer declarators: you can put in type qualifiers. Of particular interest is the very odd optimizer hint of giving an array declarator the static type modifier. Given this declaration: int foo(int a[static 10]);

It is undefined behavior to call foo() with a pointer that doesn't point to at least 10 objects of type int. This is an optimizer hint. All you're doing is promising the compiler that the argument passed to the function will be at least that large; some machines might use this for loop unrolling. As old hands will be well aware, it's not a new C standard without an entirely new meaning for the static keyword.

One last feature to mention is flexible array members. There is a common problem of wanting to declare a structure that is essentially a header followed by some data bytes. Unfortunately, C89 provided no good way to do this without giving the structure a pointer to a separately allocated region. Two common solutions included declaring a member with exactly one byte of storage, then allocating extra and overrunning the bounds of the array, and declaring a member with more storage than you could possibly need, underallocating, and being careful to use only the storage available. Both of these were problematic for some compilers, so C99 introduced a new syntax for this:

Listing 3. A structure with a flexible array

struct header {
    size_t len;
    unsigned char data[];
};

This structure has the useful property that if you allocate space for (sizeof(struct header) + 10) bytes, you can treat data as being an array of 10 bytes. This new syntax is supported in gcc.

Library features
That's fine for the compiler. What about the standard library? A lot of the library features added in C99 were based on existing practice, especially practices found in the BSD and Linux communities. So, many of these features are preexisting ones already found in the Linux and BSD standard libraries. Many of these features are simple utility functions; almost all of them could in principle be done in portable code, but many of them would be exceedingly difficult.

Some of the most convenient features added in C99 are in the printf family of functions. First, the v*scanf functions have become standardized; for every member of the scanf family, there is a corresponding v*scanf function that takes a va_list parameter instead of a variable argument list. These functions serve the same role as the v*printf functions, allowing user-defined functions that take variable argument lists and end up calling a function from the printf or scanf family to do the hard work.

Secondly, the 4.4BSD snprintf function family has been imported. The snprintf function allows you to print safely into a buffer of fixed size. When told to print no more than n bytes, snprintf guarantees that it creates a string of length no more than n-1, with a null terminator at the end of the string. However, its return code is the number of characters it would have written if n had been large enough. Thus, you can reliably find out how much buffer space you would need to format something completely. This function is available everywhere, and you should use it just about all the time; a lot of security holes have been based on buffer overruns in sprintf, and this can protect against them.

A number of new math features, including complex math features and special functions designed to help optimizing compilers for specific floating point chips are in the new standard, but not reliably implemented everywhere. If you need these functions, it is best to check on the exact platform you're targeting. The floating point environment functions are not always supported, and some platforms will not have support for IEEE arithmetic. Don't count on these new features yet.

The strftime() function has been extended in C99 to provide a few more commonly desired formatting characters. These new characters appear to be available on recent Linux and BSD systems; they aren't always widely available on somewhat older systems, though. Check the documentation before using new formats.

As noted, most of the internationalization code is not reliably implemented yet.

Other new library features are typically not universally available; the math functions are likely to be available in supercomputer compilers, and the internationalization functions are likely to be available in compilers developed outside the United States. Compiler vendors implement the features they have a call for.

... ... ...

Resources

[Aug 12 2003] Simon hates software

From: Simon Cozens
Date: 12:36 on 12 Aug 2003
Subject: G"C"C

Arthur Bergman:
> it would be fine if it wasn't for the GODAMN ANAL LINKER that AIX uses!

No, it's that gcc is a complete and utter bloody joke. It will compile and link almost anything. It would probably compile Perl without too much modification and wouldn't even emit that many warnings. Look! Look at this!

*&(int)f = 1;

Is that C? I don't fucking think so. And look at this:

FILE *
concat_fopen (char *s1, char *s2, char *mode)
{
char str[strlen (s1) + strlen (s2) + 1];
...
}

Yes, that's supposed to be C, not C++, because the things they've done to C++ are almost bloody unspeakable. The words "embrace" and "extend" come to mind. How about this, for instance:

It is very convenient to have operators which return the "minimum" or the
"maximum" of two arguments. In GNU C++ (but not in GNU C),

a <? b -- is the minimum, returning the smaller of the numeric values a and b;
a >? b -- is the maximum, returning the larger of the numeric values a and b.

What? What the hell is that about? And you know the worst thing? People actually use these abortions in real code, because obviously, if it compiles on Linux with gcc, it'll compile anywhere. That's why you're having problems linking on AIX - because nobody's even thought about AIX before. We use
autoconf, right, so it must be portable?

[Sep 24. 2003] Cyclone

A Safe Dialect of C
Download! Cyclone Version 0.6 (3.0MB, 24 Sep 2003)

Read! the documentation (download)

Join! Cyclone mailing lists or send comments

Cyclone is mirrored at Cornell and AT&T Labs Research.

Synopsis

Cyclone is a programming language based on C that is safe, meaning that it rules out programs that have buffer overflows, dangling pointers, format string attacks, and so on. High-level, type-safe languages, such as Java, Scheme, or ML also provide safety, but they don't give the same control over data representations and memory management that C does (witness the fact that the run-time systems for these languages are usually written in C.) Furthermore, porting legacy C code to these languages or interfacing with legacy C libraries is a difficult and error-prone process. The goal of Cyclone is to give programmers the same low-level control and performance of C without sacrificing safety, and to make it easy to port or interface with legacy C code.

Cyclone achieves safety while remaining compatible with C by:

Cyclone also provides modern features for convenient programming:

Software Distribution

The Cyclone compiler and tools, as well as some benchmark programs, are freely available for download.

System Requirements:

Licensing: The files in the distribution come from a variety of sources and so come under a variety of licenses. Please see each file and directory for its licensing terms.

Download Cyclone version 0.6

Download Cyclone documentation

Download Benchmarks version 0.4

Papers

Cyclone: A Safe Dialect of C, Trevor Jim, Greg Morrisett, Dan Grossman, Michael Hicks, James Cheney, and Yanling Wang. USENIX Annual Technical Conference, pages 275--288, Monterey, CA, June 2002.
PS PDF DVI

Region-based Memory Management in Cyclone, Dan Grossman, Greg Morrisett, Trevor Jim, Michael Hicks, Yanling Wang, and James Cheney. ACM Conference on Programming Language Design and Implementation, pages 282--293, Berlin, Germany, June, 2002.
PS PDF DVI
Cornell CS Technical Report TR2001-1856 contains the full definition and safety proof for the formal language sketched in the paper: PS PDF DVI

Safe and Flexible Memory Management in Cyclone, Mike Hicks, Greg Morrisett, Dan Grossman, and Trevor Jim. University of Maryland Technical Report CS-TR-4514, July 2003.
This paper describes how we have integrated unique pointers, reference counted objects, and dynamic regions into the language.

More information

Mailing Lists: We have set up three mailing lists for public use:

Go to http://lists.cs.cornell.edu/mailman/listinfo/ to subscribe/unsubscribe, or click the links below to send a message (only list members may submit to Cyclone-l).

Credits: Cyclone is a joint project of AT&T Labs Research and Greg Morrisett's group at Cornell University; see the Acknowledgments section of the documentation for details. Here are some links to personal web pages:

Trevor Jim
Greg Morrisett
Dan Grossman
James Cheney
Mike Hicks
Mathieu Baudet
Matthew Harris
Yanling Wang

C Elements of Style

C Elements of Style was published by M&T books in 1992. An abbrivated copy of the book is presented here. This book covers only the C language and is a bit out dated. However it still contains a lot of good advice. Note: The HTML conversion is not perfect. If you want things nicely formatted, get the PDF version.
Table of Contents HTML Format PDF Format
Chapter 1: Style and Program Organization HTML Format PDF Format
Chapter 2: File Basics, Comments, and Program Headings HTML Format PDF Format
Chapter 3: Variable Names HTML Format PDF Format
Chapter 4: Statement Formatting HTML Format PDF Format
Chapter 5: Statement Details HTML Format PDF Format
Chapter 6: Preprocessor HTML Format PDF Format
Chapter 7: Directory Organization and Makefile Style HTML Format PDF Format
Chapter 8: User-Friendly Programming HTML Format PDF Format
Chapter 9: Rules HTML Format PDF Format

Open Watcom - Portable Compilers and Tools

Open Watcom is a joint effort between SciTech Software Inc, Sybase®, and the Open Source development community to maintain and enhance the Sybase Watcom C/C++ and Fortran compiler products. Plans for Open Watcom include porting the compiler to the Linux and FreeBSD platforms, as well as updating the compilers to support the latest C and C++ ANSI standards.

The Open Watcom development team has released version 1.1. You can download the source and binaries here.

To keep up with the latest news, participate in the Open Watcom community

Intel® Compiters

icc The New Intel C Compiler for Linux by Jake Jenkins

Table of Contents:
Overview
The Good
The Bad
Optimization Switches
Performance vs. GCC
Caveats

Overview

Recently, Intel released its newest compilers for C/C++ and Fortran77/90 for the Linux platform. Calling them simply C++ and Fortran Compilers 5.0 does a them bit of disservice. These compilers have been long awaited by developers and it seems the wait has been worth it. Most serious developers on the Intel architecture know that while these processors are capable of performance rivaling that of high end workstation CPU's, making the Intel's peak performance available required the purchase of commercial libraries or hours of tedious assembly coding. This is due to the fact that there exists on every Intel processor since the Pentium III, a special feature known as SSE. SSE is really just a marketing term for the Pentium III and later's high powered floating point unit. SSE is actually composed of 8 128bit registers whose sole purpose is to perform floating point arithmetic. As you will see later in the article, utilizing these extra registers to their fullest potential can lead to tremendous performance increases in applications which make heavy use of floating point calculations.

The Good

Fortunately for those of us who use Linux, the compilers can be had for free for non-commercial use. For Windows users in an academic environment, the cost is relatively low as well at under $100 per user.

Links

Intel

A good benchmark repository

MCSR

[SLL] A small page about the Intel C-C++ compiler

Take a look at http://developer.intel.com/software/products/eval/

Note that Linux products have two links:
30-day Free Evaluation Software (Includes Support)
Non-Commercial Unsupported Software

I wrote a small document months ago (when there was only available beta
releases) about installing the compiler, but now its outdated (the
non-commercial version doesn't require you to mess with the temible flex
license manager :-)

Small Tip for Debian Potato users: choose the Red Hat 6.2 on IA-32
Processors, do an apt-get install rpm and you should have no problems
installing it

About the GCC efficiency (or lack of it): All I can say is that much has been
discussed about this issue and the conclusión I most often hear is that GCC
strength is not in the efficency of the generated binary (which is not so bad
in some platforms) but its portability (you can find a gcc _everywhere_).
Haven't tested gcc 3.x yet, but seems that a lot of work has been done in
this subject (anyone here has experiences with the 3.x branch?)

About the fortran compiler: haven't used it, but I'm pretty sure it has full
fortran 95 support (as well as other goodies like openMP).

FTR: The intel compilers (at least the C/C++ one) are based on the KAI
compiler set (take a look at www.kai.com)

Regards
Pedro

Best Practices for Programming in C

A typical style-related recipes for C without any new insights, but still the paper has a reasonably balanced approach to the topic. As always some tips are questionable. I doubt that declaration of the counter in the loop (for(int i=0; i<100; i++) array[i]=0;) is a portable construct. A lot of C-compilers will reject this. As one of Linux Today readers noted "...if you copy things verbatim from others, *including comments* etc, it would be nicer to name the original authors, ie (?) Henry Spencer ('Ten commandments for C programmers') and Robert Pike ('Notes on programming in C'). But this certainly doesn't ever happen in code written by IBM-employees, does it?"

On a positive side they note usefulness goto in organizing breaks from inner loops:

Sean Etc.f


mytype_t* foo (char* string);

Problematic C Declarations:
char* string, not_a_string;

Usual Ugly C Style:
mytype_t *foo (char *string);
char *string, *string2;
string = *other_string;

bject: Re: Best practices about C hmm ( Jul 28, 2003, 14:17:31 )


for(i=0 to 100)
array[i]=0

I would write the following instead:
for(int i=0; i<100; i++) array[i]=0;

Actually, to ensure the scope of the variable i is limited to the current construct, the use of curly brackets is recommended.

for (int i; i<100; i++) { array[i]=0; }

This way the variable named 'i' can be reused within the same function without contamination and as a debugging aid. Nobody writes perfect code the first time do they?

Torvalds: What, me worry? (an interview with Linux Torvalds)

CNET.com

Are there other open-source software development communities you particularly admire?
If I'd have to pick two, I'd pick KDE and the GCC group. I often end up clashing with the compiler people, because the kernel ends up having rather strict needs, and I hate how much slower GCC has become over the years. But there's no question that they're doing some good stuff.

... ... ...

I was talking to (Red Hat Chief Technology Officer and GCC backer) Michael Tiemann about his view that general-purpose compilers, well written, will incorporate broad optimizations that ultimately will produce superior code to compilers with chip-specific optimizations. But now I'm hearing that Intel's C compiler produces much faster software than GCC. Have you tried the Intel compilers, now that you can compile Linux with them?

I haven't really ever gotten around to using the Intel compilers, but I like the fact that there is competition and a baseline to compare against.

And I personally disagree with Michael about general-purpose compilers. Yes, there should be a lot of shared code, but when it comes down to it, the thing that matters most for modern CPUs is just generating good tight code, and the generic optimizations aren't that interesting. But hey, that's just my personal opinion. I'm not really a huge compiler person; I just don't like how the high-level optimizations in current GCC versions are slowing things down without actually giving much of a boost to generated code for C.

Programming in standard C and C++

Dr. Dobb's Journal Interview with Alex Stepanov

Let's consider now why C is a great language. It is commonly believed that C is a hack which was successful because Unix was written in it. I disagree. Over a long period of time computer architectures evolved, not because of some clever people figuring how to evolve architectures---as a matter of fact, clever people were pushing tagged architectures during that period of time---but because of the demands of different programmers to solve real problems. Computers that were able to deal just with numbers evolved into computers with byte-addressable memory, flat address spaces, and pointers. This was a natural evolution reflecting the growing set of problems that people were solving. C, reflecting the genius of Dennis Ritchie, provided a minimal model of the computer that had evolved over 30 years. C was not a quick hack. As computers evolved to handle all kinds of problems, C, being the minimal model of such a computer, became a very powerful language to solve all kinds of problems in different domains very effectively. This is the secret of C's portability: it is the best representation of an abstract computer that we have. Of course, the abstraction is done over the set of real computers, not some imaginary computational devices. Moreover, people could understand the machine model behind C. It is much easier for an average engineer to understand the machine model behind C than the machine model behind Ada or even Scheme. C succeeded because it was doing the right thing, not because of AT&T promoting it or Unix being written with it.

[May 12, 2003] ONLamp.com What I Hate About Your Programming Language What I Hate About C

Unix.se - Interview - Dennis Ritchie

C is declining somewhat in usage compared to C++, and maybe Java, but perhaps even more compared to higher-level scripting languages. It's still fairly strong for the basic system-type things.

Do you agree with Rob Pike's thoughts on the (ir)relevance of systems research? (http://cm.bell-labs.com/who/rob/utah2000.ps)

Dennis Ritchie: Pretty much, although Rob was stating his case in a deliberately provocative way. It's true that compared with the scene when Unix started, today the ecological niches are fairly full, and fresh new OS ideas are harder to come by, or at least to propagate.

Any thoughts about the GNU project? How did you first learn about it?

Dennis Ritchie: I can't remember when I first learned about it, but a long time ago. The True-GNU philosophy is more extreme than I care for, but it certainly laid a foundation for the current scene, as well as providing real software.

The interesting thing is the way that free-software ideas have begun to influence major existing commercial players.

At the same time, much of it seems to have to do with recreating things we or others had already done; it seems rather derivative intellectually; is there a dearth of really new ideas? But still, it's a great satisfaction that so much of it has built on top of a basis we helped to establish.

Recommended Links

New:

Top:

Other:


See also

Bookshelf


Tutorials

See also TutorialSearch Two good books on C are available online. So do not waste  time browsing the WEB searching for tutorials -- use www.informit.com and save time.  Believe me it would be difficult to find something even close to the quality of a published book on the WEB, unless this is a WEB variant of a published book ;-).  All reference below are supplementary. You can also try to buy a decent book , actually you can do this for approximately the cost of your monthly WEB access ;-).  As for sites with similar collections of links also LEARN CC++ TODAY - a list of C/C++ tutorials by Vinit Carpenter (old, last updated in 1996),  and CSS Program Web Library; C programming.

These notes are part of the UW Experimental College course on Introductory C Programming. They are based on notes prepared (beginning in Spring, 1995) to supplement the book The C Programming Language, by Brian Kernighan and Dennis Ritchie, or K&R as the book and its authors are affectionately known. (The second edition was published in 1988 by Prentice-Hall, ISBN 0-13-110362-8.) These notes are now (as of Winter, 1995-6) intended to be stand-alone, although the sections are still cross-referenced to those of K&R, for the reader who wants to pursue a more in-depth exposition.

Learn C Programming --  a learning CD with an audio track

Notes on Writing Portable Programs in C

University Courses


Articles


FAQs


References

K&R


Standard Library


Code Examples / Snippets


Pointers and arrays

Every pointer in C has an associated type. The type of a pointer instructs the compiler how to interpret the memory found at a particular address -- basically how many bytes one element of this data type should span.

A pointer is defined by prefixing the identifier with the dereference operator (*). In the following example, ip is intended as a pointer to an object of type int, and i2 is interpreted as a data object of type int:

int  *ip, i2;

If the value of a pointer is 0 (NULL), that mean that it does not point to any object at all.


GCC

Other implementations


MS Visual C

 The best way to buy is to by one of the books with CD   This way you can get Visual C++ v.6.0 Teaching Edition for less than $50


Turbo C/Borland C

The cheapest way to buy compiler is to buy one of the  books with compiler on CD  


EiC

 EiC  -- EiC is a freely available C language interpreter in both source and binary form. EiC allows you to write C programs, and then "execute" them as if they were a script (like a Perl script or a shell script). You can even embed EiC in your own programs, allowing your application to have a "scripting" language that is syntactically equivalent to C. It is also possible to let an EiC "script" call compiled library code and for compiled code to make callbacks to EiC user defined functions.

[ Jul 8, 2000] Linux Magazine: EiC: I Can C Clearly NOW

"Edmond Breen's EiC (Embeddable/Extensible Interactive C) is an open source program that provides one of the most complete and well-designed language interpreters we've ever seen."


Optimization of code


Typical Errors

Lint is a great tool. repeat after me lint is a great tool and if somebody is not using it he/she is does not respect himself and his time... It's simply stupid to spent time debugging errors that lint can find.

  1. Non-terminated comment, "accidentally" terminated by some subsequent comment, with the code in between swallowed.
            a=b; /* this is a bug
            c=d; /* c=d will never happen */
  2. Accidental assignment/Accidental Booleans
            if(a=b) c;      /* a always equals b */

    Depending on your viewpont, the bug in the language is that the assignment operator is too easy to confuse with the equality operator; or maybe the bug is that C doesn't much care what constitutes a boolean expression: (a=b) is not a boolean expression! (but C doesn't care)


Lint, Debugging

See also Softpanorama Debugging Links

Typical errors


C critique

Programming Language Critiques -- collection of papers. Not maintained

The Case Against C, P. J. Moylam, Technical Report EE9240, Department of Electrical and Computer Engineering, The University of Newcastle, July 1992. (see also Moylan The case against C.). The author raise some interesting points, but generally he does not understand that the flexibility and quality of implementation are an integral part of the quality of the language and that efficiency still matters in libraries and other products. Pascal was nicw inroductory programming language, but really horrible system programming language because of this fundamentalist typing. Modula is an improvement, but still it might be that Wirth was barking to the wrong tree ;-).  His critique of pointers is simply naive (Goto of data structures ;-)

It is not my intention in this note to debate the relative merits of procedural (e.g. Pascal or C), functional (e.g. Lisp), and declarative languages (e.g. Prolog). That is a separate issue. My intention, rather, is to urge people using a procedural language to give preference to high-level languages.

In what follows, I shall be using Modula-2 as an example of a modern programming language. This is simply because it is a language about which I can talk intelligently. I am not suggesting that Modula-2 is perfect; but it at least serves to illustrate that there are languages which do not have the failings of C.

Why C remains popular

With advances in compiler technology, the original motivation for designing medium-level languages - namely, object code efficiency - has largely disappeared. Most other machine-oriented languages which appeared at about the same time as C are now considered to be obsolete. Why, then, has C survived?

There is of course a belief that C is more appealing to the "macho" side of programmers, who enjoy the challenge of struggling with obscure bugs and of finding obscure and tricky ways of doing things.

The conciseness of C code is also a popular feature. C programmers seem to feel that being able to write a statement like


**p++^=q++=*r---s 

is a major argument in favour of using C, since it saves keystrokes. A cynic might suggest that the saving will be offset by the need for additional comments, but a glance at some typical C programs will show that comments are also considered to be a waste of keystrokes, even among so-called professional programmers.

... ... ...

Another important factor is that initial program development is perceived to be faster in C than in a more structured language. (I don't agree with this belief, and will return later to this point.) The general perception is that a lot of forward planning is necessary in a language like Modula-2, whereas with C one can sit down and start coding immediately, giving more immediate gratification.

Do these reasons look familiar? Yes, they are almost identical to the arguments which were being trotted out a few years ago in favour of BASIC. Could it be that the current crop of C programmers are the same people who were playing with toy computers as adolescents? We said at the time that using BASIC as a first language would create bad habits which would be very difficult to eradicate. Now we're seeing the evidence of that.

Nothing in this document should be interpreted as a criticism of the original designers of C. I happen to believe that the language was an excellent invention for its time. I am simply suggesting that there have been some advances in the art and science of software design since that time, and that we ought to be taking advantage of them.

I am not so naive as to expect that diatribes such as this will cause the language to die out. Loyalty to a language is very largely an emotional issue which is not subject to rational debate. I would hope, however, that I can convince at least some people to re-think their positions.

I recognise, too, that factors other than the inherent quality of a language can be important. Compiler availability is one such factor. Re-use of existing software is another; it can dictate the continued use of a language even when it is clearly not the best choice on other grounds. (Indeed, I continue to use the language myself for some projects, mainly for this reason.) What we need to guard against, however, is making inappropriate choices through simple inertia.


Unix Programming


Random Findings


Etc

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available in our efforts to advance understanding of environmental, political, human rights, economic, democracy, scientific, and social justice issues, etc. We believe this constitutes a 'fair use' of any such copyrighted material as provided for in section 107 of the US Copyright Law. In accordance with Title 17 U.S.C. Section 107, the material on this site is distributed without profit exclusivly for research and educational purposes.   If you wish to use copyrighted material from this site for purposes of your own that go beyond 'fair use', you must obtain permission from the copyright owner. 

ABUSE: IPs or network segments from which we detect a stream of probes might be blocked for no less then 90 days. Multiple types of probes increase this period.  

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least


Copyright © 1996-2016 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License.

The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to make a contribution, supporting development of this site and speed up access. In case softpanorama.org is down you can use the at softpanorama.info

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.

Last modified: October 20, 2015