8 ms·
Where to begin when learning C? Start by making lots of errors
- morganwilde 13y agoBy the way, I would love any feedback on this approach and where I should take this further.
- e12e 13y agoI'm surprised no-one's mentioned it yet, but this approach should go well with Zed Shaw's Learn C the Hard Way: http://c.learncodethehardway.org/book/
- e12e 13y agoAs for going further staying with the bare-bones approach, I suppose you'd have to start looking at assembly output and how that fits with what the c-code does. I don't know anything about OSX x86_64 calling conventions etc -- but at least under Linux (and afaik windows) 64bits is a lot more friendly and fun than the mess that was 32bit (and 16bit) x86. There are a couple of great (free) resources on 32bit x86 assembly I'm aware of: http://www.drpaulcarter.com/pcasm/ http://www.drpaulcarter.com/pcasm/ http://www.plantation-productions.com/Webster/HighLevelAsm/index.html http://www.plantation-productions.com/Webster/HighLevelAsm/i... There's apparently some plans on upgrading HLA to x86_64 -- I don't know of any good tutorials or guides on working on 64bit assembly specifically I'm afraid. Just adding "-S" and looking at the source can be helpful of course, although I much prefer nasm/intel syntax, for clang/gcc that should require: clang -S -mllvm --x86-asm-syntax=intel main.c gcc -S -masm=intel main.c Note that gas syntax is the "default" in the gnu-world, so it might be easier to just go with that if you're just starting out. It looks like clang might be generating less "noise" for tiny trivial programs, here's a side by-side-diff (in intel syntax) of int main{} vs int main { return 0;} (slightly reformatted): diff --side-by-side main.s main.no-ret .file "main.c" .file "main.c" .text .text .globl main .globl main .align 16, 0x90 .align 16, 0x90 .type main,@function .type main,@function main: # @main main: # @main .cfi_startproc .cfi_startproc # BB#0: # %entry # BB#0: # %entry mov EAX, 0 mov EAX, 0 mov DWORD PTR [RSP - 4], 0 < ret ret .Ltmp0: .Ltmp0: .size main, .Ltmp0-main .size main, .Ltmp0-main .cfi_endproc .cfi_endproc .section ".note.GNU-stack","",@progbits .section ".note.GNU-stack","",@progbits It can be fun to do this with stuff like hello world (and contrast puts("Hello, world!"); with printf("Hello world!\n);).
- morganwilde 13y agoe12e, this is something I didn't think about, but fits perfectly into me theme of "zooming out". Thanks!
- pjmlp 13y agoIntel x86 assemblers family are so much nice that whatever any UNIX system has.
- jdeisenberg 13y agoThe error message says: Undefined symbols for architecture x86_64: "_main" (etc.) If someone truly knows nothing about C, how does that person go from that error message to "In the case for C, the entry point is defined by the “main()” function." I'm not clear on where the beginner is going to go to "dig deeper and understand what it is that it’s trying to say."
- pjmlp 13y agoBy making sure to enable all warnings, enable warnings as errors and use a compiler that integrates static analysis like clang.
- morganwilde 13y agoI am using the default `cc` compiler on Mac OS X for this without any flags, are you saying I should something non-stock in this case?
- enqk 13y agoTry passing at least the -Wall and -Wextra flags. For learning, you could also add -ansi, as it will make your compiler be stricter about standards.
- zokier 13y agoinstead of -ansi, i'd argue that -std=c99 (or -std=c11) would be more appropriate. also note the -pedantic flag.
- e12e 13y agoAnd probably -Werror (all warnings become errors, breaking compilation). Fun post. Now I know why everyone was raving about the clang error-messages: echo "void main() {}" > main.c gcc -Wall -Werror --std=c99 main.c main.c:1:6: error: return type of ‘main’ is not ‘int’ [-Werror=main] cc1: all warnings being treated as errors clang -Wall -Werror --std=c99 main.c main.c:1:1: error: 'main' must return 'int' void main() {} ^ 1 error generated. (not showing clangs pretty colours)
- morganwilde 13y agoNice suggestion. Although I can't seem where one would have to look for those "pretty colours" you mentioned, I certainly can't see any of them on my Mac terminal...
- kabdib 13y agoI learned C by reading K and R and doing the book's exercises . . . on paper. At the time I didn't have access to a C compiler, so I wrote them all out in a notebook. A month later I got a job at a shop that was running Unix, and got the chance to type my programs in and try them. I had a lot of things wrong. It took me a while to understand the difference between control-D and EOF, for instance (how embarrassing). But the 30 days I spent without a compiler made me think about program behavior. I'm not saying this is a great way to learn a language, but it can be done. I keep hearing people complain about K and R being "a terrible book." For me it was perfect: pragmatic, succinct, with great examples and good exercises.
- morganwilde 13y agoI guess this is sort of I'm thinking about this, that is forcing people first to think how something should work, rather then just duplicating some code and seeing that it works. Thanks for sharing!
- jaxytee 13y agoI find the visceral act of manually writing code to be an extremely effective tool when learning programming language syntax. I find it similar to the "Write these words 10 times" technique used when teaching grade school kids how to spell and read.
- gits1225 13y ago"Programming is learned by writing programs" - Brain Kernighan And that is what anyone who goes through K&R will do: Reading and writing lots of real programs. A simple program is worth a thousand words! Which unfortunately the majority of technical books just can't get right. Explain the concepts in 5 full dull pages, and then at the end "Hey, checkout this little snippet of code, which by the way does nothing really interesting, but is here to illustrate what the author was talking about :)"
- DanWaterworth 13y ago> A simple program is worth a thousand words! Whereas, the less said about complicated code, the better.
- tptacek 13y agoThis situation is why there is "hello world"; that program seems trivial but actually has important implications; for instance, that your environment works, that you know how to feed programs to the compiler, that you can actually run the output. I never took "hello world" seriously until I started doing embedded systems work; it's now an extraordinarily important tool for me (I work an anomalously weird number of different environments).
- mrmekon 13y agoI once had a particularly slow week at work, and decided to write an article about how "Hello World" works in C. How it really works -- including compiling, linking, system calls, operating system involvement, hardware I/O, communication between ICs, etc. The path from the block of text to photons emitting from the screen, with fairly detailed explanations at every level. I ended up with a 50 page LaTeX document that barely even scratched the surface, and then work picked up and I never finished it. A "full" explanation would probably be a 600+ page book. I still think it would be a neat resource to have. We kind of take for granted that the simple "Hello World" is built on 60 years of research, and is anything but simple.
- morganwilde 13y agoWOW, you should post that LaTeX document regardless of it being unfinished! Just the fact that you spent so much effort, requires some sort of release :)
- wglb 13y agoI have often had the same idea, but more towards the goal of the intended audience being non-programmers. But if you do finish this, I certainly would be interested in reading it.
- purringmeow 13y agoCan you please post it somewhere? I am really curious!
- Aeolus98 13y ago
- mbq 13y agoActually the message quoted complains about the lack of _main not main, so the rest of this post is a huge overinterpretation. _main is IMO some windoizm connected to the use of WinMain for GUI apps.
- morganwilde 13y agoAre you trying to dispute the fact that `main()` is THE entry point for any C program? I'd be interested in hearing a more comprehensive explanation.
- mbq 13y agoTo some extent, _start is (https://blogs.oracle.com/ksplice/entry/hello_from_a_libc_free https://blogs.oracle.com/ksplice/entry/hello_from_a_libc_fre...), so you can make a working program that has no main(). And in general entry points are a quirky land heavily dependent on OS and compilation stack.
- simias 13y agoA C program starts at the function "main", what you're discussing here is beyond the scope of the C language. C without the libc or any other form of runtime is not standard C. I'm not trying to nitpick but I'm worried newcomers to the language might be misled by your comments, the things you're talking about are not a concern for most coders unless they have to do things like low level embedded code, bootloaders and things like that. And then your entrypoint won't be "start" anyway, it'll be the reset vector or some lower stage jumping to a specific address for instance.
- lhgaghl 13y agoThis is stupid. You should learn C properly (know how to avoid undefined behavior) or not at all. Exception if you're doing something that can tolerate remote code execution.
- b0rsuk 13y agoInstall Valgrind. It makes error messages a lot less cryptic (my #1 problem with C... not that's it's limited to C). If you don't get proper feedback, it's not learning, just banging your head against the wall.
- ufo 13y agoIn a similar vain, learn how to use a debugger, such as GDB or DDD. Even the bare minimum (getting a stack trace from a crashing/segfaulting program) is incredibly helpful.
- adregan 13y agoI've had a heck of a time getting Valgrind working on a mac (especially since Mavericks), hardly finding any resources about it. Is there an alternative, or do you have any advice on getting it to work?
- mtdewcmu 13y agoXCode comes with profiling tools. It's not easy to stray outside of Apple's own development tools.
- laveur 13y agoThis all of this!
- yetanotherphd 13y agoI think I have some ingrained fear of making errors, from the days where a simple error might cause your program to chew through your whole hard drive. Actually I don't know if that was ever the case, but that's how I felt. Anyway, the hardest step for me in learning a language is when I take some running code and make one change to see what happens. Once I get in the swing of it, it gets much easier, but that first step is still hard to do.
- passfree 13y agoYou should learn go instead of C.
- morganwilde 13y agoA valid point longterm, but for different reasons that I have for discussing C.
- foster1890 13y agoWhere to begin when learning C? Start at http://c.learncodethehardway.org/ http://c.learncodethehardway.org/. It's going to be tough to top Zed Shaw's approach. The best way to learn code is by writing code.
- vparikh 13y agoIn order to for people to really understand C and be proficient in it very clearly, I always recommend that they learn the basics of programming (memory, basic types, looping structures and array manipulation) in a simple assembly language such as 6502. This helps immensely with understanding pointers and deciphering the many cryptic C compiler messages.
- mtdewcmu 13y agoA minor point, but important to understand: the error came from the linker, not the compiler. It compiled just fine.
- joshguthrie 13y agoRegarding that: >an empty file is not a valid C program, and the compiler will not hesitate to tell that to you with a big, fat error message. Didn't someone win a IOCCC some years ago by providing an empty file that got compiled successfully?
- mtdewcmu 13y agoWell, compiling an empty file is a piece of cake. An empty file is valid C, just not a complete program.
- eonil 13y agoI thinks this is a good approach. Checking most of possible exceptional cases while following regular learning course. Errors = safety nets are usually the main reason to make stiff learning curve. This would be a great help for them.
- idoescompooters 13y agoCurrently, I'm learning Python and have been learning it for over a year now. I've been thinking about moving to C as my next language. Is this a good idea? I'm eventually going to want to learn C++, but I'm not going to learn Java until I have to. Also, what are some really good C learning resources? I know there's K&R and learncthehardway.org
- agumonkey 13y agoAs other people said earlier, reading existing code is great, when you have good sources. I'm an almost noob in C, and currently reading Ian Piumarta sources[1], I find they're superb in presentation and design. http://piumarta.com/software/ http://piumarta.com/software/ [1] mostly for maru, his lisp system, but even tty2html (ascii control -> html) is very clean and elegant.