Well now I feel old. When I was in high school, CS was a required course for graduation and it was taught in C++ (that being the pedagogical language of the APCS exam). It wasn't even that long ago (late 1990's).
Why I Chose to Learn C
51–60 of 78 posts
Re: Why I Chose to Learn C
#52Earlier quoted context omitted.
Of course, I did not say assembly is just like Lisp in every respect. But as long as we're picking nits -- It is of course completely possible to create executable code during runtime, using assembler. Often not advisable. (Recall the punch line of: http://www.cs.utah.edu/~elb/folklore/mel.html )
Reading the story on the link made me feel envy :) I admire those who really understand how it all works under the hoods. Although I tried to learn assembly on my own a long time ago, I never went much further than reading some imput and printing it to the screen. It seems it is a very specialized knowledge nowdays.
Re: Why I Chose to Learn C
#53Earlier 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…
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.
Re: Why I Chose to Learn C
#54Quote below from Learning C the Hard Way " For Windows users I'll show you how to get a basic Ubuntu Linux system up and running in a virtual machine so that you can still do all of my exercises, but avoid all the painful Windows installation problems. " A bootable Ubuntu USB stick with persistent storage might be easier to get started with? Can be created from a Live CD. Interesting idea.
Re: Why I Chose to Learn C
#55For 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…
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?
Re: Why I Chose to Learn C
#56Well now I feel old. When I was in high school, CS was a required course for graduation and it was taught in C++ (that being the pedagogical language of the APCS exam). It wasn't even that long ago (late 1990's).
Variables are declared like this:
name : type;
for example, here is an integer i and a pointer to an integer p: i : integer;
p : ^integer;
^ reads like "pointer to" here.If you want to point p to i's address:
p := @i;
@ reads like "address of" here. "at" also makes sense. By the way := is the assignment operator.And if you want to assign a value to what a pointer points to (in other words, deference it), you can:
p^ := 42;
The equivalent C would be: int i;
int *p;
p = &i;
*p = 42;
I guess it's not that different.Re: Why I Chose to Learn C
#57C programming is still alive and well is many parts of our profession. The biggest reason why is that even though c++ _can_ do memory management like C most of the time programs implemented in it don't and you can really start to loose a grasp as to what your asking the computer to do when you abstract away where your putting all the stuff your unknowingly asking it to make.
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…
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 different allocation semantics were Very Hard(TM) for me to understand at first. I kept battling w/ the type checker, throwing different pointer types at it until the example compiled. (Rust's compiler is _very_ intelligent, w/o using "unsafe" code, you basically cannot have a "use after free" condition in Rust. -- It will not compile.)
As the parent points out: I've never really spent any length of time _understanding_ the allocations I'm asking a computer to make. I just generate things, they become garbage, and the runtime cleans it up eventually.
Once Rust "clicked" for me, I realized something: I know the lifetime of _every single variable_ in this piece of code.
I know when it's allocated, where it's allocated, and when it gets freed.
The reason it was so hard for me to initially grok Rust was because I'm _not used to reasoning_ about memory allocation.
Once I understood the semantics though, it was as though I had an _entirely new_ level of abstraction at my fingertips.
These semantics are definitely some powerful stuff, and I'm very glad I'm taking the time to try and understand them.
[0]: http://pcwalton.github.com/blog/2013/03/18/an-overview-of-me...
Re: Why I Chose to Learn C
#58Earlier quoted context omitted.
Here's another surprising (but fully understandable) perspective given in the OP: "Function pointers — It was interesting to me to see that such a low-level language contained functional programming concepts." If you started from assembly and worked up, this looks very different, because at that very low level, functions and data look the same too. (Just like Lisp).
How is that assembly has code as data just like Lisp? Is it possible to create executable code during runtime, change the language's syntax, and stuff like that, using assembly?
You aren't going to have the expressiveness that a Lisp provides available to you, but self-modifying code and macros assemblers are common in some assembly programming scenes. Anything to save a few bytes or cycles. I'm a little rusty, but here's a basic example off the top of my head (sorry, wall of text incoming):
Functional programmers are familiar with the concept of "map," an operation that applies a function to every element in a list or what have you. Let's say I'm programming in 6502 assembly, and I have a little function that adds an amount to every byte in a page (or every byte in some particular 256 bytes). Let's say you also want a similar function that instead multiplies each byte by two (just a single left shift), or masks some bits off with a bitwise AND, or whatever. It would look something like this:
store zero in X register, add constant to the memory at the address (some constant address + value in X register), increment X, branch back to the adding part if the zero flag is not set (ie, loop until X overflows to 0), then return to wherever we called this function from.
You could write a handful of these almost identical subroutines, with the only real difference being the single opcode that reads, modifies, and rewrites each byte... or you could just rewrite the opcode at runtime!
Now, your add-to-page, multiply-page, mask-out-page, and any similar functions all share a little block of code that you can think of as "their map," and the actual functions you call initially could look something like this:
Write the constant for the relevant opcode to the instruction in map you want to replace ($7D for ADC absolute,X on the 6502), and jump to the map subroutine.
That's a bit of a contrived example, but in a routine with a more complicated access pattern, it might really make a difference in byte savings: Imagine a routine that clips offscreen entities in a game, that calculates something like "if their X coordinate is below or above some value, they disappear for now. If their Y coordinate is below some value, they fell into a pit and died." You could reuse a lot of the general logic for checking the left edge of the screen for the other two edges, just by rewriting a constant and instruction or two.
A perhaps more readily useful example is rewriting "constant" addresses. How would we rewrite our above "map" routine to modify arbitrary pages, and not just one in particular? We could store the address of the page we want to modify in memory, and use an indirect addressing mode for add. Indirect addressing modes of instructions do something like this: Load two bytes from some address in memory, and treat that as the address we want to operate on. Problem is, this indirect address mode adds two cycles to every operation we perform when compared to the original constant-address map. Suddenly, we're wasting over 500 cycles per map!
The solution is instead to treat the "constant" address in the instruction stream of the map routine as your address variable. Just rewrite those two bytes during your "function prologue," and voila, you have a general-purpose map routine that only uses half-a-dozen cycles or so more than one that only worked on a certain page.
The part I've been leaving out is using assembler macros to automate a lot of this stuff for you. Again, I'm rusty, and I never got all that experienced in writing macros, but someone could very easily write themself a macro (if they're using a powerful macro assembler, like ca65) that takes a single argument, the instruction you want to execute in your map, and generates for that stub subroutine that replaces the opcode for them. I found simpler macros to be more useful in everyday code, though: you make a macro that fills in a gap in the 6502's instruction set, like performing arithmetic between the accumulator and index registers, or basic 16-bit arithmetic, and from then on, you can pretend that the CPU had those instructions all along.
I may have only used these techniques for shaving bytes and cycles off of straightforward routines, but in some ways, going from writing 6502 assembler to writing C, Lua, and JavaScript actually feels like a step back in terms of expressiveness, even if they are certainly more productive languages in actuality, and first-class functions/function pointers cover much of the most practical (and least dangerous) use-cases for self-modifying code. I suppose I won't get that feeling back until I set some time aside to really learn a Lisp.
Re: Why I Chose to Learn C
#59For 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 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.
Re: Why I Chose to Learn C
#60Earlier 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.
There is nothing to get. They're just text, inserted wherever you told the preprocessor to insert that text, exactly as if you had typed the whole lot in yourself. What you choose to do with this ability is up to you. Many people choose to use it to avoid having to copy the same text over and over again into other files.