Live data from Hacker News

Basics of Memory Addresses in C

denniskubes.com

11–18 of 18 posts

Re: Basics of Memory Addresses in C

#11
post #6

The fastest way to grok memory issues is to do some work in Assembly. Few programmers will use Assembly for regular work, but the intuition it fosters will serve you everywhere.

For MSVC:

cl /FAsc source.c/source.cpp gives you assembly right there from the command line. For gcc: gcc -S

For dumping disassembly: DUMPBIN, or LINK /DUMP for MSVC, objdump -d/-D for binutils based (gcc, and others).

Debuggers: WinDBG (free), OllyDbg (Windows), gdb/ddd even WinGDB (not free)

Re: Basics of Memory Addresses in C

#12
post #3

Nice introduction. I think it is worth pointing out that much of what you discuss is implementation dependent, the c standard doesn't require an implementation to lay out data in memory in any particular way. Instead it requires that access semantics behave in a particular way. These semantics, in turn, align with easy, low level implementations.

Er yes, virtual memory is an allowed implementation!

Re: Basics of Memory Addresses in C

#13
"Arrays are not pointers". Right. And wrong, actually.

The article says that arrays are different from pointers, but it does not prove it. It is quite simple to prove, see the program below.

Also, it's not interesting to limit the definition of arrays to just the locally and statically declared ones. If you do that then something like 90% of C programs (if not more, I think I never wrote such a C program except for exercises in class) don't use arrays at all. In all the other case (arrays passed as argument to a function, dynamically allocated arrays…), the are the same as pointers. Again, see the program below.

In reality, it is a bit pedantic to insist on this distinction, except for the rare case where it is a performance issue (the arrays of the article require one less memory access, the one to get the address of the memory at which the array starts).

    #include 
    #include 
    
    void
    f (char a[], char *b, char *c)
    {
      printf("Once passed to a function as arguments:\n\n");
    
      printf("What the article limits the definition of array to:\n");
      printf("&a      = %p\n", &a);
      printf("a       = %p\n", a);
      printf("&(a[0]) = %p\n", &(a[0]));
      printf("a + 1   = %p\n", a + 1);
      printf("&(a[1]) = %p\n", &(a[1]));
      printf("\n");
    
      printf("Pointer to an array:\n");
      printf("&b      = %p\n", &b);
      printf("b       = %p\n", b);
      printf("&(b[0]) = %p\n", &(b[0]));
      printf("b + 1   = %p\n", b + 1);
      printf("&(b[1]) = %p\n", &(b[1]));
      printf("\n");
    
      printf("Pointer to dynamically allocated memory:\n");
      printf("&c      = %p\n", &c);
      printf("c       = %p\n", c);
      printf("&(c[0]) = %p\n", &(c[0]));
      printf("c + 1   = %p\n", c + 1);
      printf("&(c[1]) = %p\n", &(c[1]));
      printf("\n");
    }
    
    int
    main (int argc, char *argv[])
    {
      char a[4];
      char *b = a;
      char *c = malloc(sizeof(*c) * 4);
    
      printf("What the article limits the definition of array to:\n");
      printf("&a      = %p\n", &a); /* behavior differs only here, this is the
                                       difference with pointers */
      printf("a       = %p\n", a);
      printf("&(a[0]) = %p\n", &(a[0]));
      printf("a + 1   = %p\n", a + 1);
      printf("&(a[1]) = %p\n", &(a[1]));
      printf("\n");
    
      printf("Pointer to an array:\n");
      printf("&b      = %p\n", &b);
      printf("b       = %p\n", b);
      printf("&(b[0]) = %p\n", &(b[0]));
      printf("b + 1   = %p\n", b + 1);
      printf("&(b[1]) = %p\n", &(b[1]));
      printf("\n");
    
      printf("Pointer to dynamically allocated memory:\n");
      printf("&c      = %p\n", &c);
      printf("c       = %p\n", c);
      printf("&(c[0]) = %p\n", &(c[0]));
      printf("c + 1   = %p\n", c + 1);
      printf("&(c[1]) = %p\n", &(c[1]));
      printf("\n");
    
      f(a, b, c);
    
      return 0;
    }
Here is a possible output of this program:

    What the article limits the definition of array to:
    &a      = 0x7fff5590ff00
    a       = 0x7fff5590ff00
    &(a[0]) = 0x7fff5590ff00
    a + 1   = 0x7fff5590ff01
    &(a[1]) = 0x7fff5590ff01
    
    Pointer to an array:
    &b      = 0x7fff5590fef8
    b       = 0x7fff5590ff00
    &(b[0]) = 0x7fff5590ff00
    b + 1   = 0x7fff5590ff01
    &(b[1]) = 0x7fff5590ff01
    
    Pointer to dynamically allocated memory:
    &c      = 0x7fff5590fef0
    c       = 0x202f010
    &(c[0]) = 0x202f010
    c + 1   = 0x202f011
    &(c[1]) = 0x202f011
    
    Once passed to a function as arguments:
    
    What the article limits the definition of array to:
    &a      = 0x7fff5590fec8
    a       = 0x7fff5590ff00
    &(a[0]) = 0x7fff5590ff00
    a + 1   = 0x7fff5590ff01
    &(a[1]) = 0x7fff5590ff01
    
    Pointer to an array:
    &b      = 0x7fff5590fec0
    b       = 0x7fff5590ff00
    &(b[0]) = 0x7fff5590ff00
    b + 1   = 0x7fff5590ff01
    &(b[1]) = 0x7fff5590ff01
    
    Pointer to dynamically allocated memory:
    &c      = 0x7fff5590feb8
    c       = 0x202f010
    &(c[0]) = 0x202f010
    c + 1   = 0x202f011
    &(c[1]) = 0x202f011
As we can see, for their practical use arrays and pointers can really be seen as the same thing. So again, except if you are optimizing a program where you can statically declare your arrays and access them a lot (i.e., you are doing matrix multiplication), the difference between arrays and pointers does not really matter.

Re: Basics of Memory Addresses in C

#14
I appreciate the distinction between arrays and pointers, but the article fails to mention a similar pitfall: A struct is the sizeof its members., which isn't necessarily true.

It's like how everyone learns that (INT_MAX + 1) == INT_MIN (even non-developers seems to know this) yet that it actually is undefined (in C/C++), I feel that just noting that it isn't the whole truth (such as noting that the OS handles the memory behind your back) is quite valuable, even when learning the basics.

Otherwise you might end up feeling, as I do, that your foundation is shaky and built up on lies - not really knowing what "facts" you can trust.

Re: Basics of Memory Addresses in C

#15
post #6

The fastest way to grok memory issues is to do some work in Assembly. Few programmers will use Assembly for regular work, but the intuition it fosters will serve you everywhere.

I think this is a very good advice, but for me it was the other way around: using assembly was easy when I had to because I already grok the pointers from C.

I remember in a programming language course we had to write a compiler for a subset of OCaml to MIPS assembly. I had literally no trouble adding support for references, while for others who did not grok C pointers (or had never programmed in C), it was less easy.

Re: Basics of Memory Addresses in C

#16
post #13

"Arrays are not pointers". Right. And wrong, actually. The article says that arrays are different from pointers, but it does not prove it. It is quite simple to prove, see the program below. Also, it's not interesting to limit the definition of arrays to just the locally and statically declared ones. If you do that then something like 90% of C programs (if not more, I think I never wrote such a C program except for e…

Array is block of memory, which has address. Pointer is variable, which holds address of block of memory.

Arrays are useful when array memory can be accessed directly, without using of indirect addressing as in case of pointer.

Re: Basics of Memory Addresses in C

#17
post #6

The fastest way to grok memory issues is to do some work in Assembly. Few programmers will use Assembly for regular work, but the intuition it fosters will serve you everywhere.

> The fastest way to grok memory issues is to do some work in Assembly.

And get some footing in OS design. Because, ultimately, your program's entire view of memory is just another API it uses to communicate with the OS.

Re: Basics of Memory Addresses in C

#18
post #14

I appreciate the distinction between arrays and pointers, but the article fails to mention a similar pitfall: A struct is the sizeof its members. , which isn't necessarily true. It's like how everyone learns that (INT_MAX + 1) == INT_MIN (even non-developers seems to know this) yet that it actually is undefined (in C/C++), I feel that just noting that it isn't the whole truth (such as noting that the OS handles the m…

I went through this learning experience. Something similar to a struct with 32 bit items, a 16 bit item, then a 64 bit item. The 64 bit item was being aligned to a friendly 32 bit address, which left 16 bits of unassigned memory between the 16 and 64 bit items.
Post reply on HN