12 ms·
C for high level programmers (slides)
- htor 11y agoI feel C is best summarized in these two slides: http://charliethe.ninja/slideshow/introtoc.html#22 http://charliethe.ninja/slideshow/introtoc.html#22 http://charliethe.ninja/slideshow/introtoc.html#25 http://charliethe.ninja/slideshow/introtoc.html#25
- rorykoehler 11y agoC was my first language and I find knowing it makes me a better programmer in higher level languages. Apart from that though a great intro.
- joshuapants 11y agoI just about died laughing at slide 22. Anybody know how these slides were made?
- charlesL 11y agoHey author of the slides here, glad you liked it :D I used http://remarkjs.com/ 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.
- saadel 11y agoCan you tell us what font you used?
- caipre 11y agoIt's all there in the CSS. Looks like "Amaranth" and "Droid Serif".
- agumonkey 11y agoIntersting how simple it is. `class` support is nice to grab the attention (e.g: the black slides)
- iamcreasy 11y agoI 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
- deleted 11y ago[deleted]
- kanche 11y agoI came back to the thread again just to say this. Really, that slide is gold!
- billforsternz 11y agoI was quite impressed how many important concepts are covered in such a small presentation. He explicitly doesn't cover the things in C that programmers from other domains will understand easily (functions, conditionals, loops etc.) and goes straight to the things that make C different.
- vezzy-fnord 11y agocommand line utility development, writing a replacement to systemd Those don't require direct use of C, necessarily - but rather some form of FFI to POSIX and the syscall interface. Hell, if one is writing a systemd replacement, I'd encourage use of OCaml. It'd spare you lots of boilerplate because you're writing relatively high level userspace logic, anyway.
- pjmlp 11y agoYep! Unix system programming in OCaml - https://ocaml.github.io/ocamlunix/ https://ocaml.github.io/ocamlunix/
- charlesL 11y agoHuh, I've never actually heard of using OCaml for system programming. Interesting!
- danieldk 11y agoRed Hat's Richard Jones (who is also often commenting on Hacker News) does a lot of system programming in OCaml (mostly VM management-related I think): https://rwmj.wordpress.com/tag/ocaml/ https://rwmj.wordpress.com/tag/ocaml/
- jbenner-radham 11y agoSo as someone who has an unhealthy love of C I have to say this is amazing and will be forwarding it on to some friends trying to learn C. The humor is just fantastic IMHO.
- charlesL 11y agoEhh, you can never have too much C! ;)
- qohen 11y agoMay I suggest that you also send them a link to Zed Shaw's "Learn C The Hard Way" online book [0], which presents lessons in modern C programming, including the use of tools like Valgrind, etc.? [0] http://c.learncodethehardway.org/book/ http://c.learncodethehardway.org/book/
- vegedor 11y agothis is frowned upon in irc://##c@irc.freenode.net Too many factual problems and a presentation that gets you to do things wrongly before being shown how to do it correctly, and not even always then. http://iso-9899.info/wiki/Main_Page#Stuff_that_should_be_avoided http://iso-9899.info/wiki/Main_Page#Stuff_that_should_be_avo...
- TheAceOfHearts 11y agoI just wrote a comment [0] about my problems with learning C, would you say this book covers the issues that I raised and is worth reading? EDIT: Well, I just looked over the chapters in this book and I'm now extremely excited to give it a read. It seems to cover most of the topics that I'm interested in, so thank you SO MUCH for sharing! [0] https://news.ycombinator.com/item?id=9636122 https://news.ycombinator.com/item?id=9636122
- 14113 11y agoI think it might not cover them, going by this: http://hentenaar.com/dont-learn-c-the-wrong-way http://hentenaar.com/dont-learn-c-the-wrong-way
- akkartik 11y agoNo mention of undefined behavior? That's the first thing I tell people about C, considering how easy it is to trigger.
- charlesL 11y agoThe issue with undefined behavior is it's kind of hard to... well... define. It's an odd combination of unsafe memory, float/integer rollover, and rules with memory allocation. I wasn't quite sure how to clearly state it.
- akkartik 11y agoYeah I tend not to get hung up on the different ways it can trigger. It's more like, if you trigger it your program might run fine for now and then suddenly act up one day. It might die before the undefined behavior. It might launch nukes. Still sure you want to get into this? No? Want to go back to Ruby? Well, Ruby is built atop C. That's the five states of grief I try to get them through.
- kibibu 11y agoWorse than that - undefined behaviour can cause optimization to make your software insecure. http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
- caf 11y agoAll you really need to say is: There are some rules in C which neither the compiler nor the runtime is required to check if you've broken. On the contrary, the implementation is allowed to assume that you haven't broken them - which means that if you do break these rules, all bets are off as far as the behaviour of your program goes, which may lead to all sorts of strange and apparently inconsistent results.
- vortico 11y agoThere was a mention of garbage being returned from an out of bounds array.
- chrixian 11y agoThe thing about pointers that I don't get is why do you need the memory address of the variable? Is that the only way to get the value when you want it? Like, every variable has to have a pointer in order to make use of the variable?
- andrepd 11y agoIf you want arrays of variables, you need pointers. It's not enough to know the value of an int (the first element of the array), but you need the pointer to an int (pointer to the first element of the array). Now you can increment the pointer to go to the next element. You couldn't do this with a simple value. Also, suppose you want to pass a variable of a large data type, like an image, to a function. Instead of copying the entire variable, just pass the cheap pointer. The analogy is giving someone an URL vs the source code of the site for them to paste in the browser (You can't fit the latter onto a QR code, for instance, but you can the former).
- kyllo 11y agoOf course the problem is, if you're passing a pointer to a data structure to a function, the function doesn't know the size of the data structure unless you pass that as another argument.
- xamuel 11y agoYou meant to say, "if you're passing a pointer to an array to a function, the function doesn't know the size of the array unless you pass that as another argument". When passing a (pointer to a) data structure to a function, in 99.99% of cases there's only one data structure you'd pass, and you build this into the function's prototype, e.g., int myfunction( struct my_structure *x ) instead of int myfunction( void *x ) and so, yes, the function does know the size of the structure. And in the case of arrays, often it's enough to mark the end of the array (with '\0' in the case of char arrays or NULL in the case of pointer arrays), I'd only roll my sleeves up and worry about minimizing length calculations if I had actually done some profiling and determined that such nitty-gritty optimization was needed (it rarely is).
- halayli 11y agoteaching 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.
- mappu 11y ago>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.
- halayli 11y agoIf 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.
- masklinn 11y agoAn issue which is not linux specific is when calculating the size of an array allocation you can overflow size_t. So when mallocing arrays, you're supposed to check the computed size for overflow (or use calloc(3) or OpenBSD/libbsd's reallocarray(3) instead).
- pdw 11y agoNot checking malloc's return value can easily lead to security vulnerabilities, particularly in bytecode interpreters and things like that. The basic plan is simple: Trick the target program into allocating an impossible huge block of memory (e.g. 3 gigabyte on a 32 bit system). Malloc will return NULL but the program blindly assumes the allocation has succeeded. Now use carefully chosen indices to read and write whatever memory you want. As an example, here's a classic Flash exploit that used this technique: http://chargen.matasano.com/chargen/2007/7/27/this-new-vulnerability-dowds-inhuman-flash-exploit.html http://chargen.matasano.com/chargen/2007/7/27/this-new-vulne... Really, xmalloc is five lines of code. Just use it. void *xmalloc(size_t size) { void *ptr = malloc(size); if (!ptr) abort(); return ptr; }
- StephenFalken 11y agoC is quirky, flawed, and an enormous success. While accidents of history surely helped, it evidently satisfied a need for a system implementation language efficient enough to displace assembly language, yet sufficiently abstract and fluent to describe algorithms and interactions in a wide variety of environments. -- Dennis M. Ritchie (in "The Development of the C Language" [1]) [1] http://heim.ifi.uio.no/inf2270/programmer/historien-om-C.pdf http://heim.ifi.uio.no/inf2270/programmer/historien-om-C.pdf
- deleted 11y ago[deleted]
- TheAceOfHearts 11y agoI 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 with C (and ASM). Once I knew how to debug, build, and push it onto the device, it was surprisingly easy and beautiful. There's no confusing and magical abstractions, it's just you and the hardware. You pull up the microcontroller's manual, and as long as you have an idea of what the lingo means, you can make it dance to your will. Something I disliked was that with both microcontrollers I used, there was dark magic involved in building and uploading your binary. One of the devices provided examples for a specific IDE, so I imported that example and used it as a base. I could keep modifying it and keep adding files, but I never managed to setup a "new" project. The other device was similar, but instead of using an IDE it provided a Makefile, which was nicer. Does anyone know any good resources on learning and writing real-world C? I've looked at C projects here and there over the years, with the most interesting being GNU Coreutils... But even if I can eventually understand what some code does, how do I learn why it does it that way? I'd love for a guide that showed things like: "do X and Y because of this and that", "test X and Y by running the following", "write tests using XYZ", "debug X using Tool A, and Y using Tool B", "pull in this library by copying these files into these places, and use it by adding the following lines to the following files", "generate docs by pulling in this tool and set it up by doing the following", etc. In the web world there's a massive set of problems, but it tends to be easy to find "boilerplate" generators that will get you up and running. And after you've tried out a few of them, you can usually pick up how people are mixing and matching different tools. EDIT: Another comment linked to "Learn C The Hard Way" [0], and after browsing through the chapters it seems to cover a lot of the topics I'm interested in. [0] http://c.learncodethehardway.org/book/ http://c.learncodethehardway.org/book/
- WalterBright 11y agoI never found C's transition from source code to hardware to be confusing. I struggle to comprehend why so many people, some longtime professional programmers, have trouble understanding what a linker does. On the other hand, I downloaded the CUDA SDK. I couldn't even figure out where the GPU compiled code even resided. I suppose I was just supposed to take it as it "just works" (and it did), but it all left me highly uncomfortable.
- cosmolev 11y agoC is syntactic sugar over ASM
- TickleSteve 11y ago...and Python is syntactic sugar over C. Quite often, C is the right tool for the job. That isn't likely to change.
- iopq 11y agoReally? I forgot the sugar for registers in C, can you remind me?
- allcentury 11y agoAs someone who just reread "C Programming Language", in chapter 1 they teach you how to count occurrences of characters so I'm not sure I understand the sarcastic tone of "you're not going to count foo in a file". C can be used for many things, I don't think the author of the slides dod a great job of describing "when" C is the right tool for the job.
- pkulak 11y agoI was hoping this would actually tell me how to accomplish something in C. I know all about pointers and memory, but I don't know anything about the current state if C development. What libraries do people use? What are common memory management strategies? Etc.
- yoklov 11y agoLibraries depend on what you need to do. A lot of work is done with just the std lib. For domain specific stuff you use domain specific stuff. For generic stuff, well, you tend not to want generic data structure libs that come with other languages stdlibs because its hard to do those both efficiently and cleanly (you can only pick one). Its easy enough to hack up a dynamic array or a hash table with a fixed capacity that can only insert and get, maybe delete, so you tend to do this when you need it. (Also, a sorted array usually does very well in place of a hash table with not much code) Memory managment it depend what your doing. I use a lot of arenas, and pools, and as a result very rarely have to worry too much about memory management. Some things become harder here like dynamically sized arrays, but you can do this with chunks of fixed length arrays. (or whatever) I have to do very little string processing most of the time (and when i do they usually have small, known maximum lengths), and i imagine this memory management technique would work less well for that.
- pjc50 11y agoThis depends so much on what you're doing. You get entirely different answers for embedded systems, UNIX, Windows, games, and so on.
- benwaffle 11y agohttps://notabug.org/koz.ross/awesome-c https://notabug.org/koz.ross/awesome-c
- velox_io 11y agoThis is why I like C# so much, you can go from LINQ & generics to pointers. So much versatility.
- 72deluxe 11y agoI remember someone using LINQ to do fancy things on the results of an SQL query. It was stupid. Far better would be to have written the SQL properly in the first place, instead of grabbing loads of data and doing cartwheels client-side. LINQ is neat, of course.
- _kst_ 11y agoSlide 31 says: Actually, this is how arrays are handled in C. A C array is a set of consecutive memory addresses. The first value is pointed to by a pointer. int a[] = {1, 2, 3}; // create an array // a is just a pointer to the first element... No, "a" is an array, not a pointer. Defining an array object does not create a pointer. The expression "a" is implicitly converted to a pointer to the array's first element in most but not all contexts. If "a" were nothing more than a pointer to the first element of the array, then "sizeof a" would yield the size of a pointer rather than the size of the array object. This is all explained very well in section 6 of the comp.lang.c FAQ, http://www.c-faq.com/ http://www.c-faq.com/.
- sjolsen 11y agoIt's also worth pointing out that there are no array parameters. If you write void foo (char bar [42]) { // ... } then within the scope of foo, bar will be a pointer to char, not an array of char. You can, on the other hand, write void foo (char (*bar) [42]) { // ... } in which case bar will be a pointer to array of 42 char (and notably, not a pointer to a pointer to char!). C does some very strange things. There usually is (or at least was) a good reason for it to do so, but especially if you're a beginner, you need to be on your toes if you really want to use it well.
- smilefreak 11y agoThese slides are great, I was thinking of presenting something similar to a bioinformatics lab group I am a part of. Could I adapt some of these slides?
- gshrikant 11y agoAs 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 more or less forced me to remove goto from my list of C tools). Also, the fact that it maps almost directly to asm makes it easier to reason about the generated machine code (although if that's a significant reason for using goto is questionable). [1] https://github.com/zedshaw/mongrel2/blob/master/src/http11/http11_parser.c; https://github.com/zedshaw/mongrel2/blob/master/src/http11/h... Zed Shaw's Mongrel2 server code linked to in another thread.
- yoklov 11y agoGoto 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.
- prav 11y agoAgree with above comment. Linux kernel code, especially device driver code use goto a lot.
- Gibbon1 11y agoI 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'
- eru 11y agoC is a horrible language to write a compiler in. The other reasons for `Why you should learn C' are better, though.
- kgabis 11y agoWhy? Compilation times are quite important, and writing a fast compiler is easier to achieve in C than in most other languages.
- eru 11y agoPremature optimization. Write correct first, profile then optimize later.
- kgabis 11y agoWhy is writing a compiler in C a premature optimization? Ignoring performance is just bad approach to writing software. And "premature optimization" phrase is overused, even when it's not relevant to the discussion.
- readme 11y agoFrom slide 12: int my_var = 3; // It's an int! my_var = "abc"; // COMPILER ERROR! You clearly stated that it was an int! "abc" gets interned and has a memory address. The statement my_var = "abc" tries to assign that address to my_var, but since it's not a pointer to char it gets cast to int instead, possibly truncating the value. The program still compiles, just printing a warning.
- okasaki 11y agoThese slides were full of dangerous, elementary errors when they were submitted to /r/c_programming a couple of days ago. The author doesn't know C enough to have worthwhile views on the language.
- inglor 11y agoWhy do presentations always get interpreted vs compiled wrong? It's not a property of a language it's a property of the runtime. For example Java is interpreted on old versions, JIT compiled on the desktop and compiled AoT in Android...
- nemo 11y agoCompiled vs. interpreted is intended there to mean something a little different than runtime behaviors. Compiled - source files are run through a compiler which produce some output file that's then run. With C or Java you run the .c or .java file. C compiles to an executable, Java compiles to byte code. Interpreted - source is fed to an interpreter which typically turns it into some kind of representation that's immediately run with no intermediary step on the part of the user/programmer. Perl, PHP, Ruby, Python, JS, TCL, etc. are typically run this way. The terms are inherently a little muddy, since you can compile some interpreted languages to bytecode (common in PHP, and how JRuby/Jython are often run), and in theory could write a dynamic loader for C / Java to run them as interpreted - no idea if someone has been so perverse as to do it. The behavior of a JRE or other runtime in loading bytecode/whatever to execute - JIT, AOT, or whatever has to do with how a runtime handles bytecode that's already been compiled from source and turns it to machine code to execute. The terms show up there also, but have a different meaning. That's not what people are typically discussing when they talk about a compiled vs. interpreted language, and the author was correctly using the terms when referring to languages to draw the distinction in what a developer does (rather than what a runtime does, which is basically irrelevant to C).
- Sacho 11y agoI think the parent was correct. In your explanation you even state "an interpreter which typically...". You talk about compilers and interpreters, which aren't part of the language. The way you describe it, compiled or interpreted is a transitive property of a language, based on a popular way to utilize it. If the definitions are "inherently a little muddy", then they're not very useful. Javascript and compile-to-JS languages have a ton of compilers written for them. Does that make them compiled or interpreted languages? How popular does compiling a language have to be for it to become compiled instead of interpreted? It's no wonder that the parent prefers the strict definitions which lack this ambiguity.
- bhaak 11y agoI misread the title as "C for high level programming" and was a bit confused. Of course, long time ago, C was considered a HLL. The presentation is quite good. I might point people to it in the future so they might at least have an idea in what dangerous place they want to venture.