Live data from Hacker News

Pointers in C (2010)

boredzo.org

71–80 of 113 posts

Re: Pointers in C (2010)

#71

Earlier quoted context omitted.

Dude, I've just been asked to teach c pointers and this was super helpful. Got a good c++ FAQ? :)

Marshall Cline made a good one, here's a mirror, the original seems down: http://www.dietmar-kuehl.de/mirror/c++-faq/references.html

Marshall Cline's C++ FAQ is really, really good, IMO. I had read it some years ago, I think both the online version and the book, even though I've not really worked on C++ in projects. It goes into good depth and detail, not only on C++ language features and points, but also a lot into OOP/OOAD topics. Things like why you should (sometimes) push code from the client to the server - push in the sense of shift, not in the sense of mobile code, how old code can call new code - that didn't exist when the old code was written - don't remember the full details of that one right now, it may be via virtual functions and inheritance), and many more such things, a lot of them very useful. And all written in a fun, engaging style.

Re: Pointers in C (2010)

#72

Earlier quoted context omitted.

Dude, I've just been asked to teach c pointers and this was super helpful. Got a good c++ FAQ? :)

Marshall Cline made a good one, here's a mirror, the original seems down: http://www.dietmar-kuehl.de/mirror/c++-faq/references.html

Marshall Cline’s FAQ been absorbed by the “official” C++ FAQ: https://isocpp.org/faq

Re: Pointers in C (2010)

#73
This 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.

Re: Pointers in C (2010)

#74

Earlier quoted context omitted.

The C faq presents as supposedly common questions and answers without saying what a pointer is. In contrast I really like the posts definition. > A pointer is a memory address. Not perfect but for concision and accuracy it cannot be beat.

Well, it's concise, but it leaves out something important. A C pointer has both a memory address and the type of whatever it believes it points to. The latter is what makes C-style pointer arithmetic possible, because if you know the type, you know its size too.

Right. That's why, when you have an array of structs, say each 8 bytes in size, and a pointer ptr to the start of it, each time you do:

  ptr++;
it increments the address stored in ptr, not by 1, but by 8 (bytes) - so as to now point to the next struct in the array. Same if you do:

  ptr--;
except in that case it decrements the address by 8.

And if you did:

  ptr += 2;
it would increment the address in ptr to point to 16 bytes further ahead in memory than it was earlier, for the same reason. ptr will now point to the struct which is two items further ahead in the array. So you can access that struct with the expression:

  *ptr

Re: Pointers in C (2010)

#75
post #64

Earlier quoted context omitted.

[deleted]

C pointers being typed is absolutely central. Firstly, because a pointer is typed, when we dereference it, the memory location is accessed properly as the type. We don't have to put anything in the expression to say "please access the memory as 'struct foo', or a 'double'". Secondly, arithmetic on pointers for array-like manipulation uses correct displacements for the size of the type. Thirdly, we get error checking:…

[deleted]

Re: Pointers in C (2010)

#76
post #11

Ah, 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 cla…

Pointers aren't just heap specific. Pointers are a language type that can reference memory address ( stack, heap, null or anywhere really ).

It's why you can have stack overflow, heap overflow, etc via pointer bugs.

Also, C/C++/etc runtimes don't have garbage collection but that's a runtime issue not a language specific issue/type system issue.

I think you have a good understanding of pointers, but you are mistakenly confining it to the heap or the runtime. Pointers part of the language and the type system.

Re: Pointers in C (2010)

#77
post #11

Ah, 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 cla…

My 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

Yes, that works because for an array arr and an int i,

  arr[i] (i'th element of array arr)
is the same as

  *(arr + i) (the value at the memory address arr + i)
which is the same (by commutativity) as

  *(i + arr) (the value at the memory address i + arr)
which in turn is the same as

  i[arr]
That last bit is what seems non-intuitive, but it is true.

I first read about this, maybe in the K&R book or some other C book, many years ago, at first didn't believe it, and remember trying it out on at least a Windows C compiler (MS C, likely) and maybe GCC on Linux as well. Worked on both, no compiler error.

This works because the expression arr, while we think of it as the name of the declared array, is also a synonym for the address of the first memory location of the array.

Note: all that I wrote above is what I rememeber from using ANSI C (a lot, but some years earlier). Things may have changed some with C99, etc.

Re: Pointers in C (2010)

#78
post #66

Earlier quoted context omitted.

You 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)

> 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.

I'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?

Re: Pointers in C (2010)

#79
post #12

Earlier quoted context omitted.

I'm guessing that the algorithm may be the spiral rule: http://c-faq.com/decl/spiral.anderson.html

The 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 correct rule is that postfix operators bind more tightly than unary. Declarations imitate use, so in declarators, we can regard the unary star and the postfix () and [] as unary and postfix operators. So "star star a [][]" is "star star (a [] [])".

To apply the spiral rule in these cases, we have to collapse together the chained unary and postfix operators so that the spiral traverses them as one clump:

      //        +--------+
      //        |        |
      //        |        |
          int  *** aa[2][3][4];
      //   ^    |   v    |
      //   |    |   |    |
      //   |    |   |    |
      //   +----+   +----+

"aa is an (array of array of array) of (pointer to pointer to pointer) to int".

The spiral only makes additional iterations when precedence parentheses are present. Each level of parentheses has its own postfix-unary round trip:

      //        +----------+
      //        | +----+   |
      //        | |    |   |
      //        | |    |   |
          int  **(* aa[2])[3][4];
      //   ^    | | v  |   |
      //   |    | | |  |   |
      //   |    | | |  |   |
      //   +----+ | +--+   |
      //          +--------+

Re: Pointers in C (2010)

#80
post #53

Earlier quoted context omitted.

A good exercise is to then guess why the spiral rule seems to work most of the time even though it is inherently wrong. The reason is that some types that are syntactically valid are forbidden by C/C++. You cannot have a function returning a function. A function returning an array. An array of functions. You can only have a pointer to these (function returning a pointer to function/array or an array of pointer to fun…

Aha, so the final working algorithm is "the spiral rule but with a rightward detour on arrays of arrays."

The working algorithm is that the postfix operators in declarators (just like in expressions) have higher precedence than the unary ones (just like in expressions), but are overridable with parentheses (like in you know what).

The declared identifier is, first and foremost, the clump of high precedence postfix things that are on it:

     a[3][4][5];  // a is an array of array of array

     b(int);      // b is a function

     c(int)[3];   // c is an array of functions: nonexistent
Then we consider the unaries:

     *** whatever;  // whatever of pointer to pointer to pointer
Then the declaration specifiers:

     int whatever;   // whatever of/to int
Post reply on HN