Live data from Hacker News

C for high level programmers (slides)

charliethe.ninja

71–80 of 129 posts

Re: C for high level programmers (slides)

#71
post #67
post #17

teaching C and not checking malloc, bad idea. using realloc in the way its used in this "tutorial" can cause memory leaks. realloc should be checked before reassigned because it can return NULL and that will overwrite the previous valid memory address.

>teaching C and not checking malloc, bad idea On Linux, malloc will appear to give you memory even if there is none left to give, so checking the error is not important.

If you take such assumptions when writing production software, good luck.

You need to program based on what the man page says and it's clear even in linux that it can still return a NULL when overcommit is turned off.

Re: C for high level programmers (slides)

#72
post #64
post #60

Earlier quoted context omitted.

Goto is fine. The 'harmful' style was using them in favor of ifs and loops. The things I've seen people do to avoid a goto are pretty awful though. If you ever use a 'do {} while (0)' just to break out of it, you should feel bad. Goto is much clearer and cleaner than nonsense like that.

Agree with above comment. Linux kernel code, especially device driver code use goto a lot.

I think one uses goto's for two sometimes three reasons.

1. Sometimes one feels the need to abuse exceptions. But C doesn't have exceptions. So one abuses the old goto instead.

2. Sometimes the code is far more readable if you use a goto to short circuit a complex block of code. Which will become insufferably more complicated if it has to say keep track of a trivial case. if(this and not trivial case) else this and not trivial. if(case a and not trivial case) else {if not trivial case)

3. You can use long jumps to do exception handling stuff. I've never had to actually do this.

One comment. I remember trying to read ancient code that abused goto's mostly because the programmer was desperately trying to fit everything into 4k of prom in languages that didn't support structured code. That was the kind of stuff Dijkstra was bitching about, not uses 1, 2, and 3. And actually since C has always had modern control structures goto just is not abused much in practice. Probably the opposite.

Side note.

int my_var = 3; my_var = "abc";

Just usually generates a warning when compiled. If run my_var will usually get loaded with the address of "abc". If you follow it with the statement

printf("my_var=%s\n", my_var); // this will throw a warning

It'll print 'my_var=abc'

Re: C for high level programmers (slides)

#73
post #7

I just about died laughing at slide 22. Anybody know how these slides were made?

Hey author of the slides here, glad you liked it :D I used http://remarkjs.com/ to make the slides. All you have to do is include the script, add a textfield with your content in markdown and it automatically converts to a slide show.

I enjoyed your slide very much. Can you make another slide that contrasts C and Rust?

Since presumably Rust has major improvements on both of this cases : Memory & Pointers

Re: C for high level programmers (slides)

#74
post #33

Earlier quoted context omitted.

Javascript has the same problem, but I think its worse. At least there are platform standards in C (autotools in GNU, msbuild on Win). Trying to figure out how Grunt/Gulp/Broccoli, LESS/SASS/Stylus/Jade, Coffeescript, Uglify, Bower, Browserify, Require.js, AMD/CommonJS, NPM etc all work together is a nightmare. It's all too hard, so people added Yeoman, Brunch, or other things to generate application configs - but no…

Yep. I'm more comfortable with Make than I am with JSPM/NPM and System.js. The process to minify my javascript and CSS and then replace the paths in the HTML so my pages actually work seems to be needlessly complex. I'm seriously considering whether I can use Make for my production website builds - the only issue is Windows support.

You have a couple of options with make under windows.

There are native versions of make. Where you are using dos shell commands to do stuff. MinGW provides Posix compatible native commands. (you can use ls, cat, etc commands). You can use msys which gives you a Posix compatible build env. Finally something like Cigwin provides both a Posix compatible build env and Posix compatible runtime as well.

Re: C for high level programmers (slides)

#75
post #60

As someone who occasionally dabbles in C code, I am interested in knowing what is the modern take on `goto`s. I know they are "harmful" but I often come across code riddled with goto statements [1] and I personally feel that as long as it makes the code readable without significantly obfuscating the logic, goto is a perfectly fine way of doing things (although popular opinion and consideration for best practices have…

Goto is fine. The 'harmful' style was using them in favor of ifs and loops. The things I've seen people do to avoid a goto are pretty awful though. If you ever use a 'do {} while (0)' just to break out of it, you should feel bad. Goto is much clearer and cleaner than nonsense like that.

Some languages, eg. BASIC, used goto's instead of functions. It is easy to see how this can lead to a horrible mess of spaghetti code.

Re: C for high level programmers (slides)

#76

As someone who occasionally dabbles in C code, I am interested in knowing what is the modern take on `goto`s. I know they are "harmful" but I often come across code riddled with goto statements [1] and I personally feel that as long as it makes the code readable without significantly obfuscating the logic, goto is a perfectly fine way of doing things (although popular opinion and consideration for best practices have…

In the C code I've written, I've found there's really one major, common use for goto: stack unwinding. It usually looks something like

    status_t foo (result_t (*result))
    {
        status_t status = good;

        resource1_t r1;
        if (failed (status = get_r1 (&r1)))
            goto end;

        resource2_t r2;
        if (failed (status = get_r2 (&r2)))
            goto cleanup_r1;

        resource3_t r3;
        if (failed (status = get_r3 (&r3)))
            goto cleanup_r2;

        status = get_result (result, r1, r2, r3);

    cleanup_r3:
        release_r3 (r3);
    cleanup_r2:
        release_r2 (r2);
    cleanup_r1:
        release_r1 (r1);
    end:
        return status;
    }
Personally, though, I prefer using C++ and destructors (and, where appropriate, exceptions):

    result_t foo ()
    {
        // Allow exceptions to propagate
        auto r1 = get_r1 ();
        auto r2 = get_r2 ();
        auto r3 = get_r3 ();

        return get_result (r1, r2, r3);
    }
Exceptions aren't always appropriate, but the C++ still usually ends up a little cleaner. I would love to see something like Haskell's Maybe monad that lets you write code like the above, but returning status information instead of throwing exceptions.

Re: C for high level programmers (slides)

#77
post #33

I think the problem with learning C is that you need to learn stuff like make, autoconf, how the compiler + preprocessors work (what do all those flags even mean!?), how making "cross-platform" stuff works, how to pull in and use "libraries", C-isms, how to test, etc. C itself is a very small and simple language, but the tooling and patterns are old and mysterious. In college I learned how to program embedded systems…

Javascript has the same problem, but I think its worse. At least there are platform standards in C (autotools in GNU, msbuild on Win). Trying to figure out how Grunt/Gulp/Broccoli, LESS/SASS/Stylus/Jade, Coffeescript, Uglify, Bower, Browserify, Require.js, AMD/CommonJS, NPM etc all work together is a nightmare. It's all too hard, so people added Yeoman, Brunch, or other things to generate application configs - but no…

I'm a C guy, and I never "worry" that if I have to recompile a project I worked on 1 or 2 years ago that I'm going to have to fight the toolchain to get it going again. Make will be make, and it will work.

I have a huge concern when I do anything in Javascript about what happens in 1 or 2 years from now when I have to modify a project I built using some Yeoman scaffolding. Is it still going to work? Will those node modules still be there? Can I update them without it breaking everything?

It's really weird for me, coming from the world of C, CVS/Git, Make, Linux, etc. where it's almost _unthinkable_ to introduce changes that would break older versions. Hell even the world "old" generally means 5+ or 10+ years.

Re: C for high level programmers (slides)

#78
post #56
post #31

Earlier quoted context omitted.

You don't need the address of a variable: you can use the plain variable just fine, and most C code does a lot of that. What a pointer does is add a level of indirection: so instead of having a value "an integer" you can have a value which is "the location of an integer". A variable holding such a value can be assigned the location of any integer variable, and importantly can also be reassigned the location of a diff…

And why is this useful? Well, for high-level folks, pointers are used for roughly the same thing as reference variables in other languages. For low-level folks, sometimes you need to be able to read from / write to a specific address in memory. So if you have, for instance, a system clock device that always give you the current time if you read address 0x1234, you might do something like this: uint64 system_time; uin…

For anyone confused, HN's formatting system changed the two asterisks that give this meaning into italics-start and italics-end.

  unit64 system_time;
  unit64 *system_time_device = 0x1234; // set pointer
  system_time = *system_time_device; // read what's pointed to

Re: C for high level programmers (slides)

#79

I think the problem with learning C is that you need to learn stuff like make, autoconf, how the compiler + preprocessors work (what do all those flags even mean!?), how making "cross-platform" stuff works, how to pull in and use "libraries", C-isms, how to test, etc. C itself is a very small and simple language, but the tooling and patterns are old and mysterious. In college I learned how to program embedded systems…

Personally, the hardest part for me was keeping track of the size of everything. Coming from a higher level language, keeping track of the bits and bytes takes some getting used to. Working with arrays in C is much tougher especially when the compiler will compile almost anything you give it, and even a small mistake is catastrophic. Before C, I was pampered and took everything for granted. Now I appreciated my life…

Other systems programming languages e.g. Turbo Pascal, Modula-2, Ada, ... you don't have to track everything if you don't want to.
Post reply on HN