Live data from Hacker News

Why I Chose to Learn C

viget.com

61–70 of 78 posts

Re: Why I Chose to Learn C

#61
post #35

For those who hit a wall with C when it came time to learn pointers, I'd like to plug a YouTube video I made that people seem to really like. https://www.youtube.com/watch?v=IkyWCOUY8V4 The terminology may not be completely accurate (although I did try very hard to not say anything incorrect), but I honestly think it does a good job of showing you how to actually use pointers. I know the resident C experts will proba…

I never really got why people found pointers to be complicated. I suck at writing C code, but pointers are something I understood pretty easily. It in the name really, it's something that points to (the location of) something else. I doubt that anyone struggles to understand pointers, they/we struggle to understand the implementation of pointers in C, in some cases. If you want to explain pointers, to people from a o…

>I never really got why people found pointers to be complicated. I suck at writing C code, but pointers are something I understood pretty easily. It in the name really, it's something that points to (the location of) something else.

That's the easy part. Not many people (if any) struggle to understand that. It's all the consequences of that, and they way it interplays with various C features, that get people confused.

Re: Why I Chose to Learn C

#62
post #55
post #35

For those who hit a wall with C when it came time to learn pointers, I'd like to plug a YouTube video I made that people seem to really like. https://www.youtube.com/watch?v=IkyWCOUY8V4 The terminology may not be completely accurate (although I did try very hard to not say anything incorrect), but I honestly think it does a good job of showing you how to actually use pointers. I know the resident C experts will proba…

I'm curious what exactly it is about pointers that makes them so hard to understand. Many new programmers seem to warm up to Java "references" just fine, and they have mostly the same semantics of C pointers. Maybe it's because passing by value is conceptually harder to grasp than passing by reference, and in C you must understand both in order to use pointers?

That, and using pointers with memory management (which in Java is GC and transparent to you), and the confusing syntax p++ vs (p)++ etc.

Re: Why I Chose to Learn C

#63
post #57
post #48

Earlier quoted context omitted.

In the other hand, I find that C++'s ability to add semantics to memory management is extremely valuable in doing the right thing at all times. unique_ptr , scoped_ptr , and shared_ptr all say different things about heap memory lifetime, and those make it easier to maintain your grasp on what you're asking the computer to do. Like many things in C++, you can do that in C too (e.g. by using a variant of Hungarian nota…

I've been playing w/ Rust this past week, and I've had something of an enlightening experience related to the pointer semantics you describe. Rust's memory management works similarly to what you describe in C++[0], but things like unique_ptr, et al. are baked into the syntax and compiler. -- It's basically syntactic sugar for memory semantics. Coming from a background of GC'd languages (Java, Go, and Ruby) these diff…

The biggest problem with manual memory management is when doing software in large teams.

Suddenly you have distributed knowledge across team members with various skill levels and producing memory leaks is very easy.

Nowadays automatic memory management in the form of GC or reference counting is the way to go.

Re: Why I Chose to Learn C

#64

Earlier quoted context omitted.

I never really got why people found pointers to be complicated. I suck at writing C code, but pointers are something I understood pretty easily. It in the name really, it's something that points to (the location of) something else. I doubt that anyone struggles to understand pointers, they/we struggle to understand the implementation of pointers in C, in some cases. If you want to explain pointers, to people from a o…

I never really got why people found pointers to be complicated I find that its often badly taught using truly awful analogies that don't help and are often actively unhelpful as soon as you step outside the very narrow boundaries of the analogy. A simple and easy thing, badly taught, becomes difficult.

The top replies to this thread illustrate your point perfectly, imo

https://news.ycombinator.com/item?id=4389691

Re: Why I Chose to Learn C

#65
post #49

Earlier quoted context omitted.

Just because you understood it great the first time doesn't mean everyone is like you. I was turned off to C for a long time due to how awful my teachers were at explaining the concept. My first time being exposed to pointers was in a binary tree traversing algorithm handout given out by my teacher - it was just way too much at once.

I just think it's weird that pointers are made to be so complicated, when the part I don't get, which is header files, get no attention. Header files might be the sole reason why I didn't care for C. I don't understand them and they are never properly explained.

You are not alone. I picked up enough C syntax to write trivial programs like the "guess the number" game in it around age 13 or so, and I already understood the concept of a pointer or memory address from reading about (but not actually practicing until I was older) assembly language and old game consoles. The questions "what the hell are headers, how am I supposed to separate a program into multiple files, how am I supposed to structure my program?" kept me from even trying anything in C until I was 17, and even then it took months of fiddling/guesswork and finally stumbling across Learn C The Hard Way before I had any idea of what I was supposed to be doing instead of throwing everything in a single giant source file. I'm still rarely sure about where I'm supposed to draw the line, and languages like C that use headers to provide and control interface and visibility make it such a pain in the ass to refactor that I err on the side of large source files.

Since you seem to be asking, headers in C are mainly used to provide interfaces to functions and datatypes defined in other source files. It's basically C's kludgy way of marking things as public or private, and choosing what external functions a source file can see.

For each source file other than the main one, you write a separate header file that includes declarations of the functions in it (just `int dostuff(int arg);` without the actual implementation in curly brackets), and definitions of the publicly-visible datatypes used in it (so your struct definitions usually go in the header, not the source file). You control whether or not something is visible externally or not just based on whether or not you write a declaration or definition for it in the header, and you control which functions are visible to each source file based on which headers you include.

In a separate source file, you include the header of every source file that contains functions you want to use. Now, the compiler knows the signature of those functions, and when you write `some_function_in_another_file();` you can think of it as "setting aside space" for the function call, even if the compiler has no idea what code is actually contained within it. It just sets up the parameters it is going to pass to it, and relies on the assumption that the function will follow the rules and return a value in the right place that it can go on to use.

EDIT: I should add that the whole purpose of making the function declarations visible is so that compiler knows how to arrange the stack. It can't know what kind of code to generate unless it has some idea of what arguments the function will be passed, and what the state of the stack will be after the function is called. I'll also add that it's important to understand the difference between definitions and declarations

All source files are compiled separately into object files. When the executable is created, a program called a linker ties up the loose ends; for example, it would decide on an address to store `some_function_in_another_file()` at, and replace the "function call stub" I mentioned earlier with the code to actually call this function.

Libraries will generally use include to generate a "super header" that a user include with a single include statement and get access to every function and data type in the library. In your own code, however, it's usually better to explicitly include only the particular headers that a source file uses, only generating "super headers" for large internal modules that will be treated a bit like external libraries by the rest of your program. For example, if you were making a game, and you wrote all of your own code to draw graphics in software, it would probably smart to make a "graphics.h" that includes all of the headers in the graphics module, so that other code can access all of it with a single include. Within the graphics module, however, you would only explicitly include the certain source files that each file needed to access. At least, that's how I would do it.

You should also include each source file's header in the source file itself; if you wrote your header correctly, it will work just fine, and you can use this to catch discrepancies between the source file and the header early on.

In an ideal world, there would be no need for this. We'd have a smarter language that allowed you to just mark each datatype or function as public or private in the source file, and instead of including a header, you'd import from a source file, or import from a namespace or something. That's just the way C is, unfortunately.

If that didn't help, read Learn C The Hard Way. Opinions on it differ, but it really helped me get an understanding of problems like header files that were forming the real and frustrating roadblocks in the way of doing anything interesting in C.

Re: Why I Chose to Learn C

#66
Spending some time learning C, ML and Scheme is well worth it. Virtually all modern languages derive from these three languages - and all 3 of them are internally consistent enough to be beautiful.

Re: Why I Chose to Learn C

#67
post #63
post #57

Earlier quoted context omitted.

I've been playing w/ Rust this past week, and I've had something of an enlightening experience related to the pointer semantics you describe. Rust's memory management works similarly to what you describe in C++[0], but things like unique_ptr, et al. are baked into the syntax and compiler. -- It's basically syntactic sugar for memory semantics. Coming from a background of GC'd languages (Java, Go, and Ruby) these diff…

The biggest problem with manual memory management is when doing software in large teams. Suddenly you have distributed knowledge across team members with various skill levels and producing memory leaks is very easy. Nowadays automatic memory management in the form of GC or reference counting is the way to go.

Or you can do what c++ and rust did which is neither reference counting or GC ( yes I know rust has a GC just stay with me for a little). Its a strong and distinct message about what you plan on doing with the memory your getting. When I run across a int* i don't know what your doing with it just by seeing its type, but if I run across a shared_ptr I know its reference counted and will stick around until I am done with it and if I am the last one it will be free'd. In the same manner If i see a unique_ptr I know that if i need it I must take it from someplace and the compiler will be kind enough to tell me if I messed it up somehow.

Re: Why I Chose to Learn C

#68
post #18
post #14

Earlier quoted context omitted.

I am a diehard fan of C, and even I think that C++ is preferable past a certain size of program. Classes and templates are far too powerful to not use; just consider things like `scoped_ptr`. Just because C++ has nasty parts doesn't mean you have to use them, in my experience most of my worst experiences with C++ come from reading other peoples' code (Boost.Spirit, I'm looking at you).

I'm going to be a contrarian, and say that I've just never found a program that was more readable with classes. Classes tend to rip up your algorithms to shreds and spread them over dozens of different files, which is really painful. I've been reading through the code in libfirm lately and it's incredibly refreshing. A pass is usually in a single file (how novel!) instead of being scattered around because of the visi…

Really? Classes never made source more readable? How on earth is `Vector` or whatever less readable than rolling a custom struct and functions?

Re: Why I Chose to Learn C

#69
post #68
post #18

Earlier quoted context omitted.

I'm going to be a contrarian, and say that I've just never found a program that was more readable with classes. Classes tend to rip up your algorithms to shreds and spread them over dozens of different files, which is really painful. I've been reading through the code in libfirm lately and it's incredibly refreshing. A pass is usually in a single file (how novel!) instead of being scattered around because of the visi…

Really? Classes never made source more readable? How on earth is `Vector ` or whatever less readable than rolling a custom struct and functions?

Basic logic error (that it doesn't make things more readable doesn't mean that it's less readable).

I just don't see the big readability win going from vector_push_back(my_vec, 53) to my_vec.push_back(53)

Re: Why I Chose to Learn C

#70
post #67
post #63

Earlier quoted context omitted.

The biggest problem with manual memory management is when doing software in large teams. Suddenly you have distributed knowledge across team members with various skill levels and producing memory leaks is very easy. Nowadays automatic memory management in the form of GC or reference counting is the way to go.

Or you can do what c++ and rust did which is neither reference counting or GC ( yes I know rust has a GC just stay with me for a little). Its a strong and distinct message about what you plan on doing with the memory your getting. When I run across a int* i don't know what your doing with it just by seeing its type, but if I run across a shared_ptr I know its reference counted and will stick around until I am done wi…

I fail to see how that is not reference counting, even if implemented at library level.
Post reply on HN