Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

C question

Name: Anonymous 2013-08-03 2:00

How much is void main() saving in CPU cycles compared to int main()?

Name: Anonymous 2013-08-03 5:16

>>1
The C language is particularly rich with ways of writing a program that totally hides the original design intent and makes it easy to shoot yourself in the foot:
- Weak-typing: C implicitly converts between floats and integers, despite they being completely different and incompatible objects, while conversion between them incurs high runtime cost. This leads to inefficient code, confusion and complicates semantics. Moreover, C allows passing integer, where pointer is expected, leading to segmentation faults.
- C programmers must write the details of buffer overflow protection into their usage of buffers EVERY TIME they write input buffer code. This means that programmers simply write buffer code with out limit protections, which is expectionally flawed in terms of software design and quality standards. We don't have to imagine how many times this has caused bugs, just look to the number of security breaches and patches with "buffer overflows" as the access point. Null-terminated strings (c-strings) are inefficient and insecure, due to requirement of calculating length every time and inability to correctly handle byte of value 0, so malicious or incorrect user-input could lead to buffer overflow with segfault or unexpected string termination. While malloc always store the size of allocated array, it isn't available to the user, resulting in a waste of 4 to 8 bytes memory and a few CPU cycles per allocation, because user would have to use his own size variable.
- Despite being called "portable assembler", C doesn't expose the some of the common assembler's features, with major deficiency being the absence of non-local gotos, generated gotos and implicit stack constantly getting in the way, so you for example can't implement exceptions or garbage collection using plain C. Moreover, macro-assemblers implement more complex structures, like functions and do-while-loops using macros, while C requires them to be a part of core language. There is also no way to get the size of compiled function or force it to reside at certain memory address, making it impossible to write certain boot-loader and OS code in C. No well defined function/stack ABI means you can't write a garbage collector using plain C. Data alignment and calling-convetion features are very implicit and confusing, while in real assembler they are explicit. The general theme of C-vs-assembly argument is C being both low level and not being low-level enough, while lacking capability for abstraction, macro assemblers have, making C a badly designed half low-level language with no potential for growth - a castrated assembly with infix operators and stack bolted on top.
- Syntax of C, although mimicked by other mainstream languages, has often been criticized. For example, Kernighan and Ritchie themselves say, "C, like any other language, has its blemishes. Some of the operators have the wrong precedence; some parts of the syntax could be better." Some questionable choices of operator precedence, as mentioned by Kernighan and Ritchie, such as == binding more tightly than & and | in expressions like x & 1 == 0, which would need to be written (x & 1) == 0 to be properly evaluated. Moreover, it is easy to mistype == as =, leading to common bugs like "if (Byte = 123)" permeating C code. Ritchie's "declaration reflects use" was proven to be extremely unintuitive and confusing, particularly for function pointers. C inherits dangling else problem from Algol, because C's syntax allows ifs without matching else clause; a good design would be to solve the else problem by forcing ever if to have matching else and introducing `when X then Y` construct for "no-else" ifs, but C doesn't have good design. Finally, a large number of cryptic compound operators, such as +=, -=, *=, ++, ?:, don't make C easier to read or learn.
- Deployment of C software requires especially complicated system of Make, ./configure, Autoconf, Automake and M4 macros (in addition to C preprocessor), with numerous other external tools, like perl, flex and yacc, generating "probes" against compilation environment. Linking process isn't straightforward either, as there is no standard ABI to shared code and even static libraries, especially when C++ kicks in, leading to DLL hell and the like conditions. C code and tools produce programs that are inaccessible to outside world and cannot be inspected during runtime. Once compiled C programs are static, difficult access and upgrade and have horrible ABI, through #include files, instead of robust module system, like the symbol package system of Common Lisp. C preprocessor #include system relies on a myriad of unobvious hacks, like "#ifndef COMMON_H", "#pragma once" and "#line number filename" - combined they wont make language simple or user-friendly.
- In addition,  People are taught to program in C, instead of Lisp, because "industry demands it", so our education is based on the whims of sighted and blinkered industry bosses. More fundamentally, the majority have difficulty dealing with ideas of reflection, meta-programming, homoiconicity, and the like, and it's hard to see the point if you don't understand.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List