12 ms·
Pointers in C (2010)
- maxxxxx 8y agoI always wonder what makes pointers so difficult for some. So far I have always been able to explain it to people by drawing a linear memory space and then showing how different types are allocated. It seems to me that pointers are one the easier concepts in programming.
- user68858788 8y agoWhile I agree that a simple figure does a good job at explaining what a pointer is, it takes quite a bit longer to develop an intuitive sense of how to effectively work with pointers. In that case it's the more examples, the better.
- Apocryphon 8y agoThe syntax gets funky, as well, especially in modern eyes.
- macintux 8y agoTo add another reason they’re difficult: many non-trivial uses of pointers are in particularly hairy situations, such as navigating complex data structures.
- analognoise 8y agoCombine that with magic number offsets, the guy who wrote it retired or moved on, and the only documentation is a comment above it that says, "DONT TOUCH".
- roenxi 8y agoPointers require a very clear mental separation between the thing and the location where the thing is stored. However, in C the thing is only really identifiable by the place it is stored. If the learner's mental model of what is happening has any flaws whatsoever, it will break under that strain. There are a few complicated concepts that are very similar but not quite the same.
- rags2riches 8y agoI vaguely remember the first few times I wanted to do something more than paste magic snippets to my .emacs file. I knew nothing about Lisp and was not much of a programmer overall. The concepts of symbols and quoting were somehow really hard to grasp. It's strange now to imagine what was so hard then. I have no memory of pointers being a hurdle like that. But I guess the concepts are somewhat similar so there probably was a time like that with pointers also.
- aasasd 8y agoMy guess is, people are trying to keep variables the primary concept, and explain pointers on top of that. Hence, ‘boxes’ again crop up in an explanation of pointers. For me, everything became much more clear when I realized that the heap memory stands on its own as a concept, being a big pile of bytes instead of ‘boxes’—and implicit allocation/deallocation of variables is just a thin veil on top (muddying the matter somewhat since vars can themselves be stored in memory and point to it). Guess I had to deal with OOP before I grokked all the pointer-juggling going on behind the scenes.
- Traubenfuchs 8y agoThat's funny, I made a completely contrarian comment: I believe there is not enough talk about boxes and too much about irrelevant memory magic!
- maxxxxx 8y agoI visualize memory as a big range and variables occupy space on them. The pointer is just the first byte of that space. Once you realize that C is basically placing stuff on memory things become pretty clear I think.
- pjmlp 8y agoSame here, but then again I already knew Z80, 80x86, 68000, Basic and Pascal before I got to learn C. I guess it is a problem for those who C is the first language where they see pointers in action.
- philiplu 8y agoYeah, so much this. I did most of my programming in asm in the mid 70s to early 80s. C wasn’t available back then on most 8-bit systems I used (Z-80, 6502, 6809, 1802, SC/MP). C pointers made complete sense to me once 16-bit microcomputers showed up.
- vishnuharidas 8y agoIn my place, those who teach C/C++ doesn't have any practical knowledge on it. They are just reading out programs from the textbook.
- solarengineer 8y agoContext: This is true in many parts of India at least, where I suspect the parent is from. I used to teach C, found pointers a bit tough, then understood them after playing around a bit. General teachers of C indeed didn't have any real world exposure to programming.
- DonHopkins 8y agoDo you use "vi" or "emacs"? It's my opinion that "vi" warps your mind about how pointers work, with its cursor that can't decide whether it's BETWEEN characters and OVER characters. https://unix.stackexchange.com/questions/11402/why-does-esc-move-the-cursor-back-in-vim https://unix.stackexchange.com/questions/11402/why-does-esc-... >Why does `ESC` move the cursor back in vim? >In insert mode, the cursor is between characters, or before the first or after the last character. In normal mode, the cursor is over a character (newlines are not characters for this purpose). This is somewhat unusual: most editors always put the cursor between characters, and have most commands act on the character after (not, strictly speaking, under) the cursor. This is perhaps partly due to the fact that before GUIs, text terminals always showed the cursor on a character (underline or block, perhaps blinking). This abstraction fails in insert mode because that requires one more position (posts vs fences). >Switching between modes has to move the cursor by a half-character, so to speak. The i command moves left, to put the cursor before the character it was over. The a command moves right. Going out of insert mode (by pressing Esc) moves the cursor left if possible (if it's at the beginning of the line, it's moved right instead). >I suppose the Esc behavior sort of makes sense. Often, you're typing at the end of the line, and there Esc can only go left. So the general behavior is the most common behavior. >Think of the character under the cursor as the last interesting character, and of the insert command as a. You can repeat a Esc without moving the cursor, except that you'll be bumped one position right if you start at the beginning of a non-empty line. Also: https://superuser.com/questions/242156/make-vim-normal-mode-cursor-sit-between-characters-instead-of-on-them https://superuser.com/questions/242156/make-vim-normal-mode-... >Make VIM normal-mode cursor sit between characters instead of on them >I would really like it if the VIM cursor in normal mode could act like it does in insert mode: a line between two characters. So for example: >- Typing vd would have no effect because nothing was selected >- p and P would be the same >- i and a would be the same >Has anything like this been done? I haven't been able to find it. >Answers: >The idea that the cursor is always on a line and on a character position or column is inherent in Vim's design. If you were to try to change that, many of Vim's operations would behave differently or would not work at all. It's not a good idea. My advice would be that you learn and become accustomed to Vim's basic behavior and not try to make it behave like some other editor. – garyjohn Feb 5 '11 at 23:55 >What you want is not Vim, I'm afraid. – romainl Feb 6 '11 at 7:15 And people wonder why I still use Emacs...
- Traubenfuchs 8y agoI believe because it is taught the wrong way and with a confusing notation. We do int ptr instead of int ptr and talk about memory instead of just saying: "It is simply a box containing 1 value, we can also make a box containing a box containing the value." Luckily, I don't do C.
- deleted 8y ago[deleted]
- ape4 8y agoThat's a start but lots of beginners don't know when to use *ptr vs &thing vs ptr->member
- maxxxxx 8y agoThe syntax definitely could be improved. The equivalence of arrays and pointers is also confusing.
- _kst_ 8y agoI checked the section "Interlude: Arrays" because the relationship between pointers and arrays in C is a major sticking point. It claims that, given a declaration int array[] = { 45, 67, 89 }; the expressions "array", "&array", and "&array[0]" are all equivalent. They are not. "&array" and "&array[0]" both refer to the same memory location, but they're of different types. In the next section: "By the way, though sizeof(void) is illegal, void pointers are incremented or decremented by 1 byte." Arithmetic on void pointers is a gcc-specific extension (also supported by some other compilers). It's a constraint violation in standard C. I don't think this is the "best" article on pointers in C. I usually recommend section 6 of the comp.lang.c FAQ, http://www.c-faq.com/ http://www.c-faq.com/
- jandrese 8y agoIs there a valid use case for doing pointer arithmetic on a void pointer? It just seems so disgusting on the surface. Did someone just really not want to bother casting to uint8_t*? As for the array types, I think maybe the article is really trying to say that they'll all compile down to the same thing in the end (probably...compilers can be weird sometimes).
- torstenvl 8y agoCasting to uint8_t* is not portable either, so it's not particularly better than using compiler extensions that let you increment void*.
- simias 8y ago"char" is portable and by definition sizeof(char) == 1 and on top of that char pointers can alias other types. If I could time travel and influence the design of C the first things I'd do is change switch to break by default. The 2nd thing I'd do is rename "char" into "byte" since that's effectively what it is (and it's seldom a character these days since we often use UTF-8 or other multi-byte encodings).
- saagarjha 8y ago
- macintux 8y agoI don’t have my copy at hand, but Expert C Programming: Deep C Secrets has the best coverage of pointers and arrays I’ve seen. In particular, it supplies a useful algorithm for decoding all pointer declarations such as functions that return function pointers. https://www.goodreads.com/book/show/198207 https://www.goodreads.com/book/show/198207
- aasasd 8y agoI'm guessing that the algorithm may be the spiral rule: http://c-faq.com/decl/spiral.anderson.html http://c-faq.com/decl/spiral.anderson.html
- macintux 8y agoFrom memory, I’d say it follows that basic strategy but is a bit more verbose and easier to follow.
- palotasb 8y agoThe spiral rule is wrong. It breaks for things as simple as arrays of arrays. // +---------+ // | +--+ | // | ^ | | int /*|*/ aa[2][3]; // ^ | | | // | +------+ | // +--------------+ The correct result is "aa is a (2-element) array of a (3-element) array of ints". To get the correct interpretation, you have to know that the spiral has to avoid the "int" element after passing through "[2]". This defeats the purpose of the spiral, since the line sometimes goes through the element and sometimes it doesn't. For example if it were "int * paa[2][3]" instead, the correct order is { [2]; [3];* ; int }. Note how the star is first avoided and comes after [3]. A 2-array of a 3-array of pointer to int. How would you know when the spiral "avoids" the element on the left and when it doesn't? Well, you need to know the declaration grammar to know that [] and () bind stronger than the thing on the left, so you need to process those first. But if you know this, drawing a spiral is redundant, because you already parsed the thing. I think the spiral rule is inherently wrong and should not be reposted as a helpful cheat-sheet for parsing C/C++ declaration syntax.
- 8y ago
- Apocryphon 8y agoI've always been partial to Dennis Kubes' five minute guide: https://news.ycombinator.com/item?id=4389691 https://news.ycombinator.com/item?id=4389691
- keyle 8y agoI joked the other day to a co-worker, currently working full time in Python, that you get used to the list comprehension and other nice things of Python so much, that you'll never be able to go back to gnarlier languages like Java/C. It's just too nice. You can get python to run really fast nowadays and if you can't, you still got nim.
- anilakar 8y agoUseless, unless you can Rust it into Ethereum with a Koltin to Typescript transpiler.
- n4r9 8y agoC# and Java 8 (I believe) provide functional patterns. e.g. in C# the ToLower function which takes a string and returns a string can be used like: var lowercaseIds = ids.Select(ToLower)
- Traubenfuchs 8y agoYou believe correctly, but naturally, it's a lot more verbose: var lowercaseIds = ids.stream().map(String::toLowerCase); and an additional .collect(Collectors.toList()) if you don't want a Stream instance. (var is Java 10, though I believe it should not be used in production code, ever)
- Merad 8y ago> var is Java 10, though I believe it should not be used in production code, ever Is that your opinion of var in general, or something about Java's implementation of it? If the former, I'm really curious why, as a C# dev who's used it for many years.
- UK-Al05 8y agoI'm not a java dev, and I don't anything around introduction var into java. But I am a c# dev, and in the early days when var was introduced a lot of people avoided var because of misunderstanding of how it works. People thought it was dynamic rather than inferred, is it the same here?
- aasasd 8y agoAh, boxes again. For me, all confusion about C's pointer-happiness cleared up when I finally realized that C (and Asm, I guess) works with heap memory as a big blob of bytes, and it's programmer's job to keep the blob's contents from getting messed up―with some thinly-veiled help from the language and the compiler. Everything else, including variables, is just syntactic sugar when it points to the heap. (With the clarification that afaik variables are different when they're on the stack or registers, becoming first-class 'indivisible' entities).
- coliveira 8y agoPointers work just as well with heap allocated or stack allocated variables.
- deleted 8y ago[deleted]
- DonHopkins 8y agoMy favorite proof that C arrays and strings are actually just syntactic sugar for pointer arithmetic is that the following are all valid and equivalent: char theLetterC = "ABC"[2]; char theLetterC = *("ABC" + 2); char theLetterC = *(2 + "ABC"); char theLetterC = 2["ABC"]; "You can't prove anything about a program written in C or FORTRAN. It's really just Peek and Poke with some syntactic sugar." -Bill Joy
- huhtenberg 8y ago> Peek and Poke Now that's the words I haven't heard in a long time.
- danlugo92 8y agochar theLetterC = 2["ABC"]; Wait, what? And I thought I was good with pointers... Edit: I think I got it, is it this?: "ABC" + 2 == 2["ABC"] == *(2 + "ABC") Right?
- deleted 8y ago[deleted]
- em3rgent0rdr 8y ago"Everything you need to know about pointers in C" everything?
- dang 8y agohttps://news.ycombinator.com/item?id=18587411 https://news.ycombinator.com/item?id=18587411
- ananonymoususer 8y agoSome of the cited examples are missing underscores. E.g. "ptr a" should be "ptr_a".
- deleted 8y ago[deleted]
- kccqzy 8y agoThe title claims everything, but certainly it doesn't cover everything. It mentions const but doesn't mention volatile. It also doesn't mention restrict which is more confusing than const/volatile. It didn't mention the strict aliasing rule. It actually didn't even mention NULL.
- dang 8y agoWe uneverythinged the title above.
- User23 8y agoNo C pedantry thread would be complete without a link to one of the finest resources on the subject: https://blog.regehr.org/ https://blog.regehr.org/
- ktpsns 8y agoWhen graphical gimmics steal the show: https://boredzo.org/pointers/boxes.png https://boredzo.org/pointers/boxes.png visualizes both pointers and their target (an integer) as 3d boxes. So the sizeof(int) is the edge length of this target? Normally we see such guiding images with 2d boxes. There's nothing wrong with 3d because clearly, integers are also not 2d (they are not even 1d). However, don't associate the size of theses boxes with the memory size of an element. This overstresses the analogy and suggests the whole thing is a vector space, but it isn't.
- edoo 8y agoPointers in C are an incredibly simple concept. So simple it might take you years to master them.
- mchobbes 8y agoThis is why people think programming is difficult. That same article could have been written in a significantly less convoluted way, and had a much broader reach, particularly for people who aren't already at least moderately familiar with C.