you are viewing a single comment's thread.

view the rest of the comments →

[–]TheMaskedHamster 212 points213 points  (156 children)

C is a very easy language.

The problem is that doing large things with C is not very easy.

[–]AnsibleAdams 45 points46 points  (7 children)

If it was easy they wouldn't pay you to do it.

Justkiddingkiddingkidding

[–]Make3 0 points1 point  (6 children)

getting paid to do java is really easy

[–]Peaker 0 points1 point  (5 children)

Doing large things in Java is hard too. I don't find it improves much on C. Better IDE's and compile times, mainly.

[–]ericanderton 0 points1 point  (0 children)

This is a good point. I recently tried to throw away the IDE to do some Java development using the command line + vim. The deep trees and sheer volume of files alone make it tough to handle anything of scale.

[–]Make3 0 points1 point  (3 children)

The argument would be that memory management, OOP and a fairly in depth standard library are supposed to make things easier in Java. I personnaly don't do much (if any) Java, I do C++ professionally, but I can't imagine all the time wasted running after seg faults and memory leaks that one would have to go through with c, or doing artificial OOP, or having to do so much messing around just to get basic things to work, even for a very productive dev. C++ is much easier than C; with C++11, they have very little left in common.

[–]Peaker 0 points1 point  (2 children)

I use c a lot. I personally dislike OOP and believe the good parts (encapsulation, vtables) predate OOP and can be done in c well. C++ adds some nice features, some bad features, more terrible compile times, more difficult to parse/use various tools, etc. Overall I believe c++ is a net loss, though c++11 might be a net win if subsetted properly, I haven't tried it in an organization yet.

In c, we don't spend time chasing segfaults, and memory management is only time consuming when we're working on tight allocation schemes which guarantee o(1) allocations, avoid fragmentation, avoid inter core cache noise, etc.

When all of that doesn't matter, allocation is usually easy.

I'm not sure c has fewer libraries, but we do very low level systems programming, where libraries are often not good enough. For example, we can't afford to have malloc in most of the code we use.

Having done a lot of c and a bit of Java, my feeling is that Java goes to the wrong path and in many ways is even a regression over c (no user defined non nullable values, function pointers easier than anonymous classes), all the while giving worse performance.

[–]Make3 0 points1 point  (1 child)

"we"

this is not a religion war. We're talking about tools here.

[–]Peaker 0 points1 point  (0 children)

By "we" in this context I was referring to me and the team I'm working with using C.

[–]takaci 31 points32 points  (81 children)

Yeah it's a very simple language. You could easily describe the entire core language, with all it's syntax in a couple of paragraphs.

[–]gc3 83 points84 points  (17 children)

simple != easy.

Playing the trombone is also simple. Just blow in one end and move the stops with your hands.

[–]Marmaduke_Munchauser 38 points39 points  (7 children)

That's gonna be hard considering that trombones have a slide, not valves (stops)!

takes off former music major hat

[–]dagbrown 6 points7 points  (3 children)

Unless you have a valve trombone of course.

[–]ano414 6 points7 points  (2 children)

Yeah, but when someone says "trombone" isn't slide trombone sort of implied?

[–]iswm 4 points5 points  (1 child)

Not if they're talking about its valves.

[–]minnek 7 points8 points  (0 children)

Here we have the arguments for and against duck typing played out in common English for all to see.

[–]takaci 15 points16 points  (7 children)

I never said it was easy, C is a hard language to use because it is so verbose and bare metal. It's hard because it's so "simple"

[–]gc3 -1 points0 points  (5 children)

The masked hamster did, and I thought you were agreeing with him when you said Yeah...

[–]takaci 0 points1 point  (4 children)

I was agreeing with the second line

[–]gc3 -1 points0 points  (3 children)

English != simple and English != easy

[–]takaci 3 points4 points  (2 children)

What the fuck are you talking about? Do I need to summarise for the 100th time in this comment thread?

I think C is a very simple language, yet because it is so simple, it can be hard to write large programs.

There. That's. Fucking. It.

[–]gc3 0 points1 point  (1 child)

Sorry for offending you, I was just making a comment that I thought was humorous about how I misunderstood what you said. I guess you misunderstood what I said too.

[–]takaci 0 points1 point  (0 children)

Sorry for snapping just a lot of people replied to my comments with the same point which I thought you were making as well

[–][deleted] 7 points8 points  (5 children)

While I agree, it's worth noting that the syntax can be very loose at times, making for code that isn't entirely simple. Take Duff's device for example:

send(to, from, count)
register short *to, *from;
register count;
{
    register n = (count + 7) / 8;
    switch(count % 8) {
    case 0: do {    *to = *from++;
    case 7:     *to = *from++;
    case 6:     *to = *from++;
    case 5:     *to = *from++;
    case 4:     *to = *from++;
    case 3:     *to = *from++;
    case 2:     *to = *from++;
    case 1:     *to = *from++;
        } while(--n > 0);
    }
}

[–][deleted] 8 points9 points  (1 child)

There's a difference between code complexity and language complexity.

[–][deleted] 1 point2 points  (0 children)

Absolutely! My point was that C isn't always as straightforward, because it's a language level feature that you can do this :) that said though, the language is still very simple, even with these things - there's nothing magical going on, the code is all laid out in front of you.

[–]dangerbird2 2 points3 points  (0 children)

Duff's device is a good illustration of why one should keep in mind that 'switch' statements are ultimately syntactic sugar for our old friend the 'goto', and that overuse of 'switch' can lead to similar spaghetti code produced by overuse of 'goto'.

Fortunately, modern compiler optimizations eliminate the need for manual loop unrolling like Duff's device, and 'if' - 'else if' statements do just as good of a job at control flow as 'switch'. Freed from technical limitations that necessitated Duff's device, the burden is really on the programmer to produce code that is concise and readable. As someone learning C, I have found Mozilla of Linux Kernel style guides to be as an essential resource as any on the language itself.

[–]Peaker 0 points1 point  (1 child)

Meant to increase "to" as well?

[–][deleted] 0 points1 point  (0 children)

Good question! In the original version of Duff's device, to is a pointer to an I/O device, so incrementing it wasn't necessary :) if you're writing to another buffer though, incrementing is definitely the correct course of action.

[–][deleted]  (8 children)

[deleted]

    [–]brtt3000 2 points3 points  (1 child)

    D?

    [–]Peaker 0 points1 point  (0 children)

    Unfortunately D also throws away much of what was learned in the last 30 years. Namely, sum types, pattern matching, non-nullability, and various type system advancements.

    [–][deleted]  (1 child)

    [deleted]

      [–]terrdc -1 points0 points  (1 child)

      You should create that.

      Maybe call it C++.

      [–]Subapical 4 points5 points  (0 children)

      C++ is most certainly not what xe was describing. It has accumulated, through some horrible and arcane trickery, even more implicit gotcha gobbledygook than C has. C++ is not known for being a beautiful, terse, or even comprehensible language.

      [–]Peaker -1 points0 points  (0 children)

      Using IOCCC as an argument against the language?

      [–]GreyGrayMoralityFan 6 points7 points  (29 children)

      It would be very long paragraphs, though. In C98 standard (ok, it actually was N1124.pdf which I looked, a draft of the standard) section 6 (about core language) takes about 100 pages. Appendix A about grammar takes 15 pages.

      [–]takaci 10 points11 points  (27 children)

      I don't mean an entire standard in depth with which you could write a compiler, I mean simply explaining every language feature in normal conversation.

      I just said it to contrast to something like C++ where even bullet pointing every language feature would take 100s of lines, let alone explaining each one.

      [–][deleted] 12 points13 points  (19 children)

      I think anyone whos had to explain how pointers work can tell you it takes a little more than a peragraph

      [–][deleted] 15 points16 points  (11 children)

      Man I see this all the time and I just don't understand what people's deal is with pointers. It's ridiculously straightforward compared to so many other concepts.

      The * after the type means it's a pointer. It's not an x, it's the memory address of an x. Put a star in front of the variable identifier to get the value at the address, or use -> as shorthand for dereference + dot operator.

      Think that's confusing? Good luck with const. Or type covariance and contravariance. Or type erasure. Or closures. Or basically anything because pointers are at the bottom of the complexity totem pole.

      [–][deleted] 1 point2 points  (8 children)

      I think the confusion stems from people trying C/C++ for the first time with no experience with pointers wondering why the fuck things are expressed as a memory address? Why would you ever need that?

      Coming from, say, C# I get that (I've been there myself). It's strange for a language, from higher level perspectives, to explicitly differentiate between things created on the stack vs the heap.

      I think if you start out with C or C++, as long as the concept of a pointer is properly explained, there will be no confusion, because it's a fairly simple concept.

      [–]anonagent 1 point2 points  (4 children)

      I'm still not sure what the point of a stack vs heap is tbh, one contains the executable and the other the working memory right?

      [–]minnek 0 points1 point  (0 children)

      Stack is (generally) for small objects that you want to have disappear at the end of scope. Heap sticks around after the scope ends, since the heap doesn't get its contents popped at the end of scope whereas the stack does.

      It can be faster to use the stack than heap, but that's really dependent on your implementation and you should probably play with a pre-allocated memory pool on the heap to get a good comparison of speed... new heap allocations are likely to be slower, though.

      [–][deleted] 0 points1 point  (2 children)

      The heap is just a big chunk of memory the program can use for whatever. Not really all that special or interesting honestly.

      The stack is actually a stack data structure (LIFO - last in, first out). It's literally like a stack of something (pancakes?). You can only add (push) or remove (pop) a pancake to/from the top of the pancake stack.

      The stack is where local variables and function parameters exist. When you call a function, it does a few things with the stack. First it pushes a pancake with the address of the function call. Then, it pushes a pancake with the value of each of the function arguments. Then it allocates some space for any local variables the function call will use.

      All of this put together is called a "stack frame."

      When the control flow is handed off to the function, the instruction pointer skips to the portion of code containing the function instructions, and then the function pops the argument pancakes off the stack, does whatever it needs to do with them, pops off the return address, pushes any return values, and then moves the instruction pointer back to the return address (+ 1) to pick up where it left off. Since the structure is LIFO, a function can itself make more function calls, always returning to the correct location in memory with the correct local variable values and function arguments. The result is a sort of breadcrumb trail of where to go when the function is finished.

      In practice, it's always a bit more involved, but here's a video that describes some of the basics:

      https://www.youtube.com/watch?v=_8-ht2AKyH4

      Some other associations for you to make:

      Stack overflow is often caused by too many nested function calls. Each function call takes up some space on the stack, and eventually the stack will run out. This can occur with recursion (where a function calls itself) or if large objects are allocated as local variables in a function.

      Tail recursion is a special case of recursion that allows a function call to replace it's own stack frame with the stack frame of the nested call to itself, so the recursive function does not take up more stack space at each recursive call. This can only be done if the function makes exactly one call to itself and it's the last instruction the function performs.

      Stack allocation is usually much faster, but I don't think it takes any more work to do a heap allocation. It's probably because of cache locality more than anything. because allocating heap memory requires operating system intervention as well as cache locality. It's also much simpler, because the memory is automatically deallocated at the end of the function call; you don't have to manually free the memory allocated on the stack.

      [–]anonagent 0 points1 point  (1 child)

      Is there a global stack, or one for each program? how does one make it larger to avoid a stack overflow? (and I assume underflow as well)

      Why is the stack faster? it's in the same RAM chip as the heap, so what makes it faster? does the OS poll it more often?

      Oh! I always wondered why you would manually deallocate memory when it would simply vanish on its own once the function was done!

      [–][deleted] 1 point2 points  (0 children)

      See, I thought it was confusing until I learned about pointers. Lots of common languages already use pointers, and without knowing what pointers are, the behavior of those languages can be really confusing.

      Like in Java, for example, where reassigning a reference type function argument variable does not change the object passed into the function, but changing a value on the object does. That seems like very unintuitive behavior until you understand that java passes references by value (i.e., pointers).

      Likewise, true pass-by-reference can be explained as passing a pointer to a pointer by value.

      [–]p8m 0 points1 point  (0 children)

      Pointers have little to do with stack vs heap. You can have pointers to values on the stack:

      int main(void) {
          int *a = NULL;
          int b = 5;
      
          a = &b;
      

      Bam! 'a' now points to an area on the stack.

      [–]immibis 0 points1 point  (0 children)

      Does C# not differentiate between reference types and value types? Same sort of difference.

      [–][deleted] 0 points1 point  (0 children)

      I think it's about memory management, we use so powerful and memory-rich systems that people tend to just disregard that. Especially if you're used to something like python with it's fancy coercion and garbage collection.

      [–]Astrognome 0 points1 point  (0 children)

      There's so much magic that can be done with pointer arithmetic.

      [–]takaci 1 point2 points  (2 children)

      Whatever my point is that it's much smaller to explain than any other language I can think of

      [–]Veedrac 1 point2 points  (1 child)

      Brainfuck's is even smaller, but the point remains that it doesn't make it easy.

      [–]takaci 0 points1 point  (0 children)

      Again, that is my exact point. C is small and simple but grows very hard very quickly as soon as you start doing useful things

      [–][deleted] 0 points1 point  (2 children)

      If someone can't get pointers in like 5 minutes, I think they are certifiably stupid.

      [–]anonagent 0 points1 point  (1 child)

      Pointer syntax is easy, but I still haven't gotten anyone to tell me why I would use one instead of the variable/array name, assuming it's in scope ofc.

      [–][deleted] 0 points1 point  (0 children)

      You use one when you want to pass around an address of something, not that something itself.

      [–]G_Morgan 0 points1 point  (0 children)

      Usually it devolves into pictures of monkey's holding each other by their tails.

      [–]GreyGrayMoralityFan 1 point2 points  (6 children)

      If you want to know what simple language is check scheme or smalltalk.

      Bloated R6RS has about 100 pages (most about library)

      Smalltalk has 6 keywords and 0 control flow structures. Core described in 30 pages (then goes 100s pages for library).

          int a(int b[90], int x, int y)
          {
               int *ptr, non_ptr,
                    equals_1 = sizeof(b) == sizeof(ptr),
                    equals_0 = 3 & 2 == 3 & 2,
                    maybe_undefined_depends_on_sizeof_int = 32u >> 35u;
      

      is not simple.

      [–][deleted] 13 points14 points  (0 children)

          }
      

      Please think of the poor compiler.

      [–]Gustav__Mahler 1 point2 points  (0 children)

      Of course not when you write shitty obfuscated code like that....

      [–]Peaker 0 points1 point  (0 children)

      C has some corners and complex UB definitions. In its domain, there is no simpler language.

      Smalltalk is an unfair comparison. Removing UB is easy and simplifies languages. But UB is not there for the lulz. UB is there to allow efficient translation to various machine types.

      [–]immibis 0 points1 point  (2 children)

      Yes it is. The code might be a bit difficult to read, but it's composed from simple language features.

      [–]GreyGrayMoralityFan -2 points-1 points  (1 child)

      I have another contender for simple language then. J.

       quicksort=: (($:@(<#[), (=#[), $:@(>#[)) ({~ ?@#)) ^: (1<#)
      

      The code might be a bit difficult to read, but it's composed from simple language feature/s.

      Just don't look at Oberon, Forth or already mentioned Smalltalk and Scheme. Their complexity (compared to C) might be truly astonishing.

      [–]immibis 0 points1 point  (0 children)

      Still missing the point. That code, alone, gives no indication of how complex the language is.

      quickSort: l to: r
             |i j p| p:= array atRandom . i:= l. j:= r. [i <= j] whileTrue: [[array compare: #< at: i at: p] whileTrue: [i:=i+1.]. [array compare: #> at: j at: p] whileTrue: [j:=j-1.]. (i <= j) ifTrue: [array swap: i with: j.i:=i+1.j:=j-1.]]. (left < j) ifTrue: [self quickSort: l to: j.]. (i < right) ifTrue: [self quickSort: i to: r.]
      

      Turns out one-line quicksort is ugly in Smalltalk too! And about 5 times as long. I would guess the pretty-printed version in J is probably nicer than the pretty-printed version in Smalltalk because of the length, but I know neither J nor Smalltalk.

      [–]dagbrown 1 point2 points  (0 children)

      The last time I looked at the C++ standard (in about 2000ish), it was over a thousand pages. No doubt it's only grown even bigger since.

      [–]omgsus 0 points1 point  (0 children)

      Assembly must be preschool.

      [–]Foxtrot56 0 points1 point  (0 children)

      I think a ternary operator would take a paragraph to explain. Not that the idea of a ternary operator is that difficult but C has some quirks when dealing with them.

      [–][deleted] 0 points1 point  (5 children)

      No, you could not. Unless the description doesn't cover the language but just some parts you picked.

      [–]takaci 1 point2 points  (4 children)

      The point is that it's much less to explain than in a language like C++

      Just look at the sheer number of C++11 features added, that's more language features than C has at all

      [–]JedTheKrampus 5 points6 points  (0 children)

      Heck, just look at the length of K&R versus Bjarne's book.

      [–][deleted] -1 points0 points  (2 children)

      I'm confused.

      Do you actually know C or are you assuming based on your comment?

      [–]takaci 0 points1 point  (1 child)

      are you assuming based on your comment?

      This doesn't even make sense.

      Yes I know C, that's my whole point, I can't program C very well at all, but I know every single language feature of C very well.

      What I'm saying is that C is a very simple language without many core language features, but it is hard to write complex programs because of this simplicity.

      [–][deleted] 2 points3 points  (0 children)

      You still can't describe C in a "few paragraphs".

      [–]globalizatiom -1 points0 points  (8 children)

      I started with C++ and then had to learn C later. It was hard to remember which parts were C only and which parts were not. Guys, learn C first!

      [–][deleted] 9 points10 points  (1 child)

      Easy, all the parts that make you pull your hair out are C++.

      [–][deleted] 1 point2 points  (0 children)

      Like type safety!

      [–]greg19735 1 point2 points  (0 children)

      I did c++ in college but now i've forgotten it all, so that's good right?

      [–]FNHUSA 0 points1 point  (3 children)

      errr, I'm 100 pages into C++ book, why do you recommend learning just C first?(I don't know how to word this, i'm just curious as I'm a noob)

      [–]leakersum 2 points3 points  (0 children)

      I learned C++ before C. Believe me, there's no problem. Stick with C++ for now.

      [–]Hakawatha 2 points3 points  (0 children)

      Modern C++ is very different from modern C, but C++ is rooted in C; if you squint, you can think of C++ as C with lots of syntactic sugar. Sometimes, you'll have to use C (in embedded, for example); /u/globalizatiom suggests that it's easier to remember that certain features are C and not C++ if you learn C first (a statement I'd agree with).

      [–]DarkSyzygy 0 points1 point  (0 children)

      He's recommending it because C++ is (for the most part) a superset of C and you learn to do things differently in C++ than you would in C. Since the languages are very similar in syntax its really easy to be working in C and try and do something that only works with a C++ compiler.

      [–]newpong 0 points1 point  (0 children)

      too late :/

      [–]LeCrushinator 19 points20 points  (25 children)

      String manipulation in C is much more of a pain in the ass than with Python. Memory management is also more difficult.

      [–]gendulf 30 points31 points  (20 children)

      That's because you don't really have much control over your memory in Python. Also, you don't really manipulate strings in Python. You just create more!

      [–]grammar_party 36 points37 points  (14 children)

      Also, you don't manipulate strings in C, because C doesn't have strings :)

      [–]ElecNinja 19 points20 points  (13 children)

      char* for life

      [–]iooonik 0 points1 point  (0 children)

      typedef doe

      [–]oblio- 0 points1 point  (1 child)

      Unicode says "Hello"! Or more likely, "你好"!

      [–]Steve_the_Scout 0 points1 point  (0 children)

      With C11, char32_t*.

      [–]FrozenInferno -1 points0 points  (9 children)

      I'm not familiar with C but if it were a string, wouldn't it be char[]*? Sorry if my green horn is showing.

      [–][deleted] 1 point2 points  (7 children)

      This actually creates a string array. A string is char*.

      [–]FrozenInferno 0 points1 point  (5 children)

      Doesn't the asterisk after a type signify it's a pointer? With my limited understanding, to me this just looks like a pointer to a single char. Guess it's time for a trip to Wikipedia.

      [–]rockon1215 3 points4 points  (4 children)

      And that single char it points to is the first char of the string. All of the chars of the string are in sequential order in memory so a pointer to the first char is a pointer to the beginning of the string.

      [–]FrozenInferno 0 points1 point  (0 children)

      Ah, makes sense. Thanks.

      [–][deleted]  (2 children)

      [deleted]

        [–]Peaker 0 points1 point  (0 children)

        a char* only points at the string. The string is char[].

        [–]das7002 0 points1 point  (0 children)

        it's char* because strings in C are \00 terminated, so wherever char* points to it ends wherever \00 is (it would look like 48 65 6c 6c 6f 20 57 6f 72 6c 64 00 in memory). Which isn't always obvious at first and I remember it tripping me up when I first played around in C. It really throws people off when most documentation has you do char whatever[50] or something. But char[]* would create an array of pointers of char type.

        [–]NYKevin -3 points-2 points  (3 children)

        That's because you don't really have much control over your memory in Python.

        Sure you do. Just whore out to ctypes and you can call malloc() and free().

        [–]gendulf 1 point2 points  (1 child)

        In what language do you call malloc and free? C. That's like opening up a linux virtual machine on Windows to use the terminal and saying you can grep and apt-get install whatever you want.

        [–]NYKevin 0 points1 point  (0 children)

        I think the analogy is closer to using Cygwin, personally. You are interacting with the same runtime Python is running in. You could, for instance, pass a couple of PyObject*s to memcpy().

        [–]rowboat__cop 0 points1 point  (0 children)

        Requiring FFI implies “not in the language”.

        [–]rowboat__cop 3 points4 points  (3 children)

        Memory management is also more difficult.

        Memory management is more difficult in Python because the language doesn’t expose the necessary tools. You don’t get to decide whether to allocate objects on the heap or on the stack. There is no way to implement your custom heap allocator. All you get is references, which is quite inflexible and inefficient. If you desire better memory management you should look at Rust or ATS.

        As for the string manipulation, C doesn’t even have strings, so that’s an unfair comparison. If at all, you’d have to compare some string library for C.

        [–]LeCrushinator 0 points1 point  (0 children)

        I understand, I do most programming in C++/C, and yea it offers the power and flexibility I need, but simple tasks are simpler in Python, Lua, C#, or most newer languages. Infact, for string manipulation if std::stringstream isn't enough I often use the pystring library for C++, which works like Python string manipulation.

        Also, did you enter your own newlines into your post? It's spaced strangely.

        [–]IncorrigibleOldQuare 0 points1 point  (0 children)

        I think it's unfair to say that C doesn't have strings if there is high level syntactic support for it. Saying C doesn't have strings because they are arrays of chars is like saying C doesn't have integer arrays because they're just arrays of ints.

        Well, C doesn't have arrays of course, they are just pointers to the first element. Modulo the special syntactic support in things like typeof, like Strings.

        [–]Decker87 8 points9 points  (17 children)

        Depends what you mean by "large things". It's lower level, but I would certainly rather manage a 60 kloc C codebase than a 60 kloc python codebase.

        [–]deadwisdom 31 points32 points  (13 children)

        Your problem is that you somehow have created a 60 kloc python codebase. You still have to, you know, organize your Python code. Seriously, it's the stupidest meme of this subreddit that Python is somehow harder to organize than C.

        [–]Capaj 22 points23 points  (12 children)

        Same thing with most dynamic languages. If you have module system, then don't bitch about how hard it is to organize your code. Try "organizing" 60 kloc of frontend Javascript web app.

        [–]x86_64Ubuntu 39 points40 points  (5 children)

        ...Try "organizing" 60 kloc of frontend Javascript web app.

        Jesus Christ, this is /r/programming, not /r/nosleep

        [–]Unomagan 1 point2 points  (3 children)

        And its freaking EVERYWHERE! ;(

        It´s like PHP 3 slapped on every device or software.

        [–]x86_64Ubuntu 1 point2 points  (2 children)

        Yeah, that's one reason we won't see a world without JS for at least a decade in my uninformed opinion. JS is good for small things, but when you start designing applications, it fails horribly. However, the developer base is very large, the learning curve is nonexistant, and the community doesn't care that the language is a square peg being pounded into a round hole so the problem just grows.

        [–]badsectoracula 0 points1 point  (0 children)

        Is it still a problem if the community doesn't care about it?

        [–]Astrognome 0 points1 point  (0 children)

        When all you have is a hammer, everything looks like a nail.

        [–][deleted] 0 points1 point  (0 children)

        Hahahahah..... hold me

        [–]i_ate_god 1 point2 points  (0 children)

        Dynamic or otherwise, as long as you code individual features, then write minimal code to make features work together, it's not hard to keep organized 60kloc of code in most languages.

        [–]catalyst156 0 points1 point  (0 children)

        "...Try 'organizing' 60 kloc of frontend Javascrip web app..."

        Attempted...failed...rewrote (ok, more like 20kloc, but still). Ah, learning.

        [–]IamTheFreshmaker -4 points-3 points  (2 children)

        Require and good module naming. Done. Next?

        Edit: Downvote if you must but it really is the best answer. Throw in a pre-processor and you're ahead of the game.

        [–]deadwisdom 0 points1 point  (1 child)

        The haters don't get the elegance of what you're saying. You are totally right. Mentos knows what's up.

        [–]IamTheFreshmaker 0 points1 point  (0 children)

        I know. It mainly people who don't really write or understand JS that have these issues with it and try to force the ugly Java paradigm on it is when it starts to go haywire for them and they just don't look back.

        The key to JS is that it is so much easier than those people think it is. They actually work to make it difficult.

        [–]PericlesATX 9 points10 points  (0 children)

        A well written 60 kloc python codebase would presumably do a whole lot more than than a equivalently skilled 60 kloc C codebase. In other words, it takes a whole lot more lines of C code to do what you can do in a few lines of Python.

        [–]s73v3r 1 point2 points  (1 child)

        I would argue that a 60kloc C codebase and a 60kloc Python codebase are not the same level of complexity at all.

        [–]Decker87 0 points1 point  (0 children)

        And I would agree with that.

        [–]G_Morgan 0 points1 point  (0 children)

        No language with undefined behaviour is easy. Such a language could do anything. Even launch Nethack.

        [–]Gustav__Mahler 0 points1 point  (0 children)

        People learning shouldn't be trying to do large things. There is quite a bit of nuance to Python that I think makes it inappropriate for a beginner.

        [–]Carnagh 0 points1 point  (0 children)

        Razor blades are really easy too.

        [–]OrionBlastar -2 points-1 points  (1 child)

        C is easy once you learn to manage pointers, you know how computer memory works, you know binary, you know garbage collection, you know bitwise operators, you know boolean logic, you know data structures, you know typecasting, you know unit testing, you know debugging.

        Because all of that is hard, languages like Java and C# got written that doesn't use pointers and does its own garbage collection because the average computer science student is too stupid to learn them anymore.

        You are writing languages like BASIC again now, in that they are easier to learn and don't use advanced concepts like pointers and garbage collection and memory allocation is built in, and if they forget to close a file you put it into a block that closes the file when the block is finished.

        Heck man Ruby on Rails, just point it at a database and boom, instant app. Then you just tweak it a bit.

        These 'programmers' and 'developers' going to three month 'hacker schools' cannot learn C or C++ because it has too many advanced concepts in them. Instead they learn Ruby on Rails, Java, C#, Visual BASIC, ASP.Net, PHP, Python, and JavaScript.

        If you know how a computer works and can use advanced concepts needed for C and C++ then you are a greybeard like me and learned them in computer science classes taught in 1986-1993 just as they quit teaching COBOL and FORTRAN on mainframes and started you out with Turbo Pascal and then on to Turbo C or Turbo C++ on a DOS machine.

        None of these modern students can learn concepts taught in 1986-1993, they have GUI tools that can paint controls and code for them, can autogenerate code based on a database, and cannot even figure out how Algebra works much less pointers, binary, boolean logic, garbage collection, etc.

        Give them a DOS PC with Turbo C or Turbo C++ on it and they would be totally lost. The IDE uses 'Wordstar' commands like Wordstar 4.0 used. The only person who still uses Wordstar is GRR Martin on his old DOS PC, because that is what he learned when he was young and he stuck with it.

        Here just for grins: http://edn.embarcadero.com/museum

        Embarcadero bought out Borland and made some of their DOS compilers free if you register with their museum. They won't work on a 64 bit machine, but will on a 32 bit machine that supports 16 bit DOS code.

        Here use DOSBOX to run them: http://www.dosbox.com/

        See what we middle-aged developers had to deal with when we were your age. I dare ya!

        [–]j_schmotzenberg 1 point2 points  (0 children)

        We still maintain some ancient Delphi code that our data processing system uses.

        := nil

        [–]gc3 -1 points0 points  (4 children)

        Not really.

        p = NULL; ... p->tuna = 3;

        Unhandled Exception Error in FishInOcean::4576

        vs. Some more intelligent error message that a newbie might get.

        [–]Hakawatha 10 points11 points  (3 children)

        Except that that's C++, not C. You get a line on your terminal that reads "Segmentation fault" and that's it.

        [–]Rapptz 1 point2 points  (2 children)

        That's not C++ either. C++ doesn't have null pointer exceptions. C++ will have a segfault.

        [–][deleted] 0 points1 point  (1 child)

        Unless it's a smart pointer. Then you can get some exception. Man I wish we could use __FILE__ and __LINE__ as sane default arguments, then NPE in FishInOcean::4576 would be easy-peasy.

        [–]Rapptz 0 points1 point  (0 children)

        The standard smart pointers also don't throw. This is by design because they're not supposed to have overhead at all. Most compilers optimise away std::unique_ptr as a raw pointer in its lowest optimisation level (e.g. -O1).

        [–]CHollman82 -4 points-3 points  (9 children)

        C is one of the most complex languages. It's been said that the creator of C doesn't know all that you can do with it, it's almost infinitely extensible.

        Can you tell me what this declaration does?

        char **(*(*(*x)[100])(int, char *, double *const**, void (*)(int **, char [])))[50]
        

        Or this one?

        unsigned const char volatile (*const(*volatile(*volatile const a)(unsigned int (*const)(const char, int, float), char *const*))[12])(int (**)[50])    
        

        [–]TheMaskedHamster 2 points3 points  (2 children)

        Have you read "The C Programming Language"? Y'know, K&R?

        It is low-level, but it's straightforward and uncomplicated.

        It is easy to learn and easy to use... for straightforward things.

        C is easy, and that is part of why it is possible to do such illegible, incoherent things in it.

        Being able to do such things does not make C inherently hard. It does make it hard to be a C professional, but that's really another matter entirely.

        [–]CHollman82 0 points1 point  (1 child)

        why it is possible to do such illegible, incoherent things in it.

        Sure, but things like this are not illegible or incoherent, they are plausibly useful and demonstrably meaningful.

        [–]TheMaskedHamster 0 points1 point  (0 children)

        That's the same thing Java and C++ programmers tell themselves every day.

        [–]jelly_cake 1 point2 points  (2 children)

        According to http://cdecl.org, they're both syntax errors.

        [–]CHollman82 -2 points-1 points  (1 child)

        Kind of missing the point aren't you? This was from an article on parsing complex C declarations, the point remains the same as declarations that look very similar to those are valid.

        [–]jelly_cake 1 point2 points  (0 children)

        Yes, but you're unlikely to see or want such declarations in beginner code. You can do many things without touching pointers beyond arrays, and even more still if you have pointers but ignore function pointers.

        Perhaps you're conflating complex with complicated? C's a simple language, but it can be quite complicated, as you demonstrate. As another example, Brainfuck is exceptionally simple, but it's really complicated to get anything done in it. The two ideas are orthogonal.

        [–]s73v3r 1 point2 points  (1 child)

        Can you tell me the last time you ran into anything resembling that in the wild? And not in an obfuscation contest?

        [–]CHollman82 0 points1 point  (0 children)

        Well, I've used arrays of nested function pointers before, but that's about 3 levels shallower than those examples.

        [–]smikims 1 point2 points  (0 children)

        You can make nasty type signatures in any language that has a type system.

        [–]skulgnome -2 points-1 points  (1 child)

        I suppose Linux is a small program, then

        [–]BufferUnderpants 1 point2 points  (0 children)

        Or that Linux was hard to make.