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

Is learning C really a must for a programmer?

Name: Anonymous 2012-09-02 6:17

Many have this opinion. Somehow, by doing manual memory management allocation and garbage mangement one would become a better programmer.

I have little experience in C mainly because I can write terser and more readable code in Racket or Haskell. However I'm willing to give C a try just to learn these lessons that everybody keeps talking.

But I have a sneaking suspicion that I already know most of what is there to know. Can you list some useful lessons that a typical high level code dweller would be oblivious of?

Name: Anonymous 2012-09-03 19:43

>>40
Polymorphism in C?
Are you tossing void* around?

Name: Anonymous 2012-09-03 19:45

const int* const (*(*(*foo)(void** (*)(const char*(int**), short int*(void(void)), volatile void* (*)(int*, const volatile int(void*(void), const long**[128]), char[32])), int, const char* [5]))(long long const*** (*[5])(), short))[3];

Name: Anonymous 2012-09-03 20:05

>>41
almost every large c project has an informal unsafe object systemshould have been written in C++LISP.

Name: Anonymous 2012-09-03 20:20

>>42
Syntax error.

Name: Anonymous 2012-09-03 20:22

>>44
Use GCC and not some obscure, nigger compiler.

Problem solved.

Name: Anonymous 2012-09-03 20:36

>>45
Comeau C/C++ 4.2.45.2 (Apr 12 2001 10:06:52) for xxxx
Copyright 1988-2001 Comeau Computing.  All rights reserved.
MODE:strict errors C90

"fuckyou.c", line 1: warning: type qualifier on return type is meaningless
  const int* const (*(*(*foo)(void** (*)(const char*(int**), short int*(void(void)), volatile void* (*)(int*, const volatile int(void*(void), const long**[128]), char[32])), int, const char* [5]))(long long const*** (*[5])(), short))[3];
                                                                                                                                ^

"fuckyou.c", line 1: error: the type "long long" is nonstandard,
        Consideration: Use --long_long for this to work in strict mode
  const int* const (*(*(*foo)(void** (*)(const char*(int**), short int*(void(void)), volatile void* (*)(int*, const volatile int(void*(void), const long**[128]), char[32])), int, const char* [5]))(long long const*** (*[5])(), short))[3];
                                                                                                                                                                                                          ^

1 error detected in the compilation of "fuckyou.c".

Name: Anonymous 2012-09-04 3:06

Somehow, by doing manual memory management allocation and garbage mangement one would become a better programmer.
Why would you start that sentence with "somehow?"  If you can't see how learning memory management (I think that's what you were trying to say) makes you a better programmer, then maybe programming isn't your bag.

Name: Anonymous 2012-09-04 3:39

>>47
Shut up buttburger. Clearly he is just using that because he lacks confidence in his own opinions and seeks reassurance from the prog community

Name: Anonymous 2012-09-04 3:56

>>48
quoted for BUTTBURGER

Name: Cudder !MhMRSATORI!fR8duoqGZdD/iE5 2012-09-04 4:06

>>35
Knuth's quote is about premature optimisation, but optimisation is never premature, so it's like saying "if the moon is made of cheese, it must be cheddar".

Have you read through the entire TeX source code? I bet a lot of programmers today would say that the entire thing is "premature optimisation" and a TDWTF. If I remember correctly, there isn't a single instance of dynamic allocation, it's one huge monolithic application.

Name: Anonymous 2012-09-04 4:37

Most people recommend learning C because it teaches you the fundamentals of programming in a strict environment & stops a lot of people from pursuing programming as a career.  If you can't handle simple C coding, you'd only be a burden to whoever hired you for anything serious.   

A couple years ago, I took an intro C course in college for EE (I just needed the credits) and I've never seen so much anguish.  Pointers ruined hipster dreams.  Empowered womyn cracked under the pressure of structs.  The ubernerd who decided to bring his tank-like gaymen laptop everywhere couldn't figure out how to SSH to compile his helloworld that wasn't going to run anyway.  Absolutely delicious Schadenfreude.

Name: Anonymous 2012-09-04 4:52

>>51
Absolutely delicious indeed.

Name: Anonymous 2012-09-04 5:46

>>51

Seems like fun. I wish I hadn't skipped Uni.

Name: Anonymous 2012-09-04 5:55

>>51
fundamentals of programming in a strict environment
They should recommend Pascal instead. Pascal is a very strict and formal-looking language.

Name: Anonymous 2012-09-04 8:03

>>50
there isn't a single instance of dynamic allocation, it's one huge monolithic application.
What are you implying here? Is it merely an off hand comment?

Name: Anonymous 2012-09-04 9:05

Cudder thats crazy talk, some optimizations are obviously premature because other optimizations should precede it in priority.

TeX source code ... TDWTF.
( ≖‿≖)

If I remember correctly, there isn't a single instance of dynamic allocation
Well, sorta...

@* \[9] Dynamic memory allocation.
The \TeX\ system does nearly all of its own memory allocation, so that it
can readily be transported into environments that do not have automatic
facilities for strings, garbage collection, etc., and so that it can be in
control of what error messages the user receives. The dynamic storage
requirements of \TeX\ are handled by providing a large array |mem| in
which consecutive blocks of words are used as nodes by the \TeX\ routines.

Pointer variables are indices into this array, or into another array
called |eqtb| that will be explained later. A pointer variable might
also be a special flag that lies outside the bounds of |mem|, so we
allow pointers to assume any |halfword| value. The minimum halfword
value represents a null pointer. \TeX\ does not assume that |mem[null]| exists.

Does Standard Pascal really not have dynamic memory or was Knuth aiming to get TeX working on microcontrollers?

Name: Anonymous 2012-09-04 12:26

>>7
Symbolics did not have a C compiler

Name: Anonymous 2012-09-04 13:20

>>1
YES.

Even if you dont program in it you should be able to compile some shit in c

Name: Anonymous 2012-09-04 17:14

Yes. In fact I would add assembly language.

Name: Anonymous 2012-09-04 17:18

>>2
C is like a portable assembly language
hahaha yeah right

Name: Anonymous 2012-09-04 21:20

>>60
How is it not? It's available on any platform and generates assembly code for all platforms it supports.

Name: Anonymous 2012-09-04 21:25

>>61
Nope. You have to build a crosscompiler, which is a complicated task in itself.

Name: Anonymous 2012-09-04 21:49


#include <stdlib.h>

void main() {
    printf("hax my anus", %d);
    return 0;
}

Name: Anonymous 2012-09-04 22:00

>>62
Already done, it's called gcc. It might be bloated shit but at least it works virtually everywhere.

Name: Anonymous 2012-09-04 22:05

>>64
GCC is ugly as your fat yiddishe mama. And it is very hard to configure GCC for crosscompilation.

Name: Anonymous 2012-09-04 22:09

>>55
Using only static allocation with (or without) the stack is very common in memory constrained environments, as it ensures that memory usage will never grow past a hard limit or become fragmented. As an example, the Mars Curiosity Rover was developed according to the JPL C coding standards, part of which includes basically forbidding dynamic memory allocation in order to eliminate allocation failure-related bugs.

A common tool used in these environments is a "memory pool", basically a statically allocated chunk of memory that you can allocate and destroy (usually) fixed-size objects within. Consider a program that needs to allocate and destroy hundreds of tiny objects per second, at unpredictable intervals. Rather than using standard malloc/free and fragmenting the fuck out of your memory (similar to the situation on a disk, memory fragmentation can quickly lead to a situation where you have enough memory available to allocate something, but because there aren't any contiguous free regions large enough, the allocation fails), you statically allocate ("set aside") enough space for a few hundred of those objects and let a memory pool library handle allocations within the pool.

>>56's quote makes it sound like a ridiculous practice ("who would write their own memory allocator for a typesetting program?"), and iirc even Knuth regrets some of the technical decisions he made when developing TeX, but I'm sure it made more than enough sense back in 1978.

Name: Anonymous 2012-09-04 22:18

Name: Anonymous 2012-09-04 22:25

>>4
It's easy to see this in code written by ex-Java programmers who have migrated to C++. Object copies and new everywhere.
Aren't ex-Java programmers more likely to pass pointers by value, since it's roughly equivalent to a Java reference?

Name: Anonymous 2012-09-04 22:37

>>56

wow....

>>65

I assume by hard, you mean you don't know how to do it.

>>68

It might be a matter of awareness of the meaning of the syntax.

Name: Anonymous 2012-09-04 22:56

Let's say based on a decision, I may have an array of strings that has to hold either 10, 100, or 1000 strings.

Wouldn't it just make sense to dynamically allocate that memory? Or would you really have me believe that the best course of action is to allocate room for 1000 strings and only use 10 if needed.

The dynamic memory allocation functions return error values if they fail. So what excuse do you have to not use them, unless you're a moron who doesn't check?

Name: Anonymous 2012-09-04 23:27

>>70
#include <stdlib.h>
char *allocate10() {
  char array[10][12];
  return &array;
  }

char *allocate100() {
  char array[100][12];
  return &array;
}

char *allocate1000() {
  char array[1000][12];
  return &array;
}

void fill(char **array, int n) {
  int i;
  for (i=0; i < n; i++) {
    array[i] = "HAX MY ANUS";
  }
}

int main() {
  char** array;
  switch(rand() % 3) {
  case 0:
    array = allocate10();
    fill(array, 10);
    break;
  case 1:
    array = allocate100();
    fill(array, 100);
    break;
  case 2:
    array = allocate1000();
    fill(array, 1000);
    break;
  }
}

Name: Anonymous 2012-09-04 23:33

>>70
you really need more information on the problem to make a proper decision.

If non of the strings will escape the body of the function, every single one of them can be allocated on the stack. With this you will have trivial allocation and deallocation, giving good performance, and there will be absolutely no fragmentation, giving good memory use.

If all of the strings will persist throughout the lifetime of the program, and their values are known at compile time, they ought to be statically allocated and constant.

If the strings really need to have dynamic extent, then you have a few options. One is to use the malloc free interface, in which you ask for a block of memory of an arbitrary length, and a search will find and reserve a block for you until you later release it with free. Fragmentation is unavoidable, and will waste memory. The search for large enough blocks can become expensive once the free space is cut up and crowded by many reserved blocks. Another option is to use a garbage collector. With the freedom to move objects around, fragmentation can be eliminated. Usually there is an additional cost and complexity of the garbage collection traversals, but in the case of strings and other data types that contain no references, they can be reference counted. And then there are memory pools, which are more effective when you are allocating many objects of the same size. With memory pools allocation is trivial and fragmentation is avoidable. But the problem is that strings are not fixed length in general, and the generality of the malloc free interface is more appropriate.

>Or would you really have me believe that the best course of action is to allocate room for 1000 strings and only use 10 if needed.

If the application is ever in a state in which it couldn't handle 1000 strings, and it might happen, then the application is insecure. Even if you handle the error and prevent a segfault, it is still a failure if you can do nothing but gracefully halt the application. You have to do everything you can to prevent this from happening on the platform you are targeting.

The dynamic memory allocation functions return error values if they fail. So what excuse do you have to not use them, unless you're a moron who doesn't check?

I can only assume that you are assuming that the memory allocation function will give the same results in performance and memory use regardless of its interface.

Name: Anonymous 2012-09-04 23:33

The dynamic memory allocation functions return error values if they fail.
Not on Linux, they don't. Linux will happily tell you that all is well, and then randomly kill unsuspecting processes until there's enough memory available to make it work or until it kills something critical like init.

Name: Anonymous 2012-09-04 23:41

Name: Anonymous 2012-09-04 23:42

This topic is still very widely debated even in academia.

Some people say that learning something like C breaks you as a programmer.
Others will say the same about prolog or haskell.

Really, as a programmer, you should have a wide toolset of languages that you are competent in. If you've never used an imperative language before, C could be really beneficial.
At the least you would begin to understand that mindset.

Name: Anonymous 2012-09-04 23:49

>>73-74
An aircraft company discovered that it was cheaper to fly its planes
with less fuel on board. The planes would be lighter and use less fuel
and money was saved. On rare occasions however the amount of fuel was
insufficient, and the plane would crash. This problem was solved by
the engineers of the company by the development of a special OOF
(out-of-fuel) mechanism. In emergency cases a passenger was selected
and thrown out of the plane. (When necessary, the procedure was
repeated.)  A large body of theory was developed and many publications
were devoted to the problem of properly selecting the victim to be
ejected.  Should the victim be chosen at random? Or should one choose
the heaviest person? Or the oldest? Should passengers pay in order not
to be ejected, so that the victim would be the poorest on board? And
if for example the heaviest person was chosen, should there be a
special exception in case that was the pilot? Should first class
passengers be exempted?  Now that the OOF mechanism existed, it would
be activated every now and then, and eject passengers even when there
was no fuel shortage. The engineers are still studying precisely how
this malfunction is caused.

Name: Anonymous 2012-09-05 0:13

>>71
Ok seriously, wouldn't

char **allocate_n(int n) {
  char array[n][STRING_SIZE];
  return array;
}


Make more sense?

Name: Anonymous 2012-09-05 0:18

>>72
You recorded data from a test. There is one file for each data channel recorded. The number of channels typically ranges from 2-250.

You need to compile a list of each channel name which is found in the header of each file. Suppose that the first line of the file is the channel name if you intend of offering some code.

How do you compile an array of strings that has each channel name in order? Go on, offer the best solution. It just seems like a perfect situation to dynamically allocate memory.

Name: Anonymous 2012-09-05 0:31

>>70
I think the point of these embedded safety critical coding guidelines is to make it easy to prove how much memory you're using and knowing that you can guarantee that your memory allocations will never fail since you know the limits of the device it's running on.

Name: Anonymous 2012-09-05 0:35

>>73
They might return an error code, if your demand is completely unreasonable like (size_t) -1. I haven't met a GNU/Linux distribution that doesn't give you an error code from malloc when you do that.

All this being said, I don't think a safety critical device would ever over-commit memory and then randomly kill programs, it's even optional in Linux.

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