-3
#include <stdio.h>
#include <unistd.h>

int staticVar = 0;

int main()
{
    staticVar += 1;

    sleep(10);
    printf("Address: %x\nValue: %d\n", &staticVar, staticVar);

    return 0;
}

I'm confused how this program prints out the address of the variable "staticVar". From playing with the code I noticed that if you change the printf statement to this...

printf("Address: %x\nValue: %d\n", staticVar, staticVar);

Then the value of the variable "staticVar" is printed in the "Address" position.

Some quick research led me to understand that the addition of "&" meant that the variable "staticVar" was being referenced and that the "%x" in the printf statement prints out the value in hex. Even with this information I am still confused as to why this works.

I also read online that you can print out the address to some variable with this line...

printf("Address: %p\n", (void*) &staticVar);

Is there advantage to doing it this way?

I may just need an explanation to what the "&" symbol effectively does.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 2
    If you don't understand `&`, how did you get to trying to understand virtual memory? – user253751 Sep 19 '16 at 02:11
  • 1
    I thought learning about operating systems sounded cool so I picked up a book. I don't know C or C++ in a considerable sense. This is normally how I learn things either way. Virtual memory at the level I'm at is purely conceptual. At the current moment I don't care to know how the OS goes from a virtual address to a physical one because, as I read, this is a difficult process. Down the line I will though. – Clark Bell Sep 19 '16 at 02:19
  • Enable warnings and resolve all reported warnings. Your code invokes undefined behaviour. `%x` is an invalid conversion type specifier for a pointer! And before starting working on OS, pick a book about C or C++. They are different languages, so choose the one you want to learn. Learn the language first, the about OS programming. – too honest for this site Sep 19 '16 at 02:37
  • C has no references, the `&` unary operator is also called "address of" operator. – too honest for this site Sep 19 '16 at 02:40
  • My plan was to learn C as I went along with the OS book. I don't think I can bare learning a language outright like I did with Java. I did find a C book that I like so I'll try to reference that whenever I need C programming help. – Clark Bell Sep 19 '16 at 02:45

2 Answers2

2

First of all, you should familiarize yourself with the concept of a pointer. Fortunately there are loads of great references out there like this (The first 5 sections are what is important).

After doing some pointer reading, the bottom line is that & is an operator in C that returns the address of the variable it precedes. (It actually can have two uses depending on the context it is used in, the other is a bitwise AND operator, but you shouldn't worry about that until you need to use it).

Also, you should always use %p to print out a pointer. The reason is because it makes your code more portable to different operating systems.

 printf("Address: %p\n", (void*) &staticVar);

This code will work, however I would not cast to a void pointer, because that typecast is unnecessary and makes the code less readable. Try this instead.

 printf("Address: %p\n", &staticVar);
Community
  • 1
  • 1
GandhiGandhi
  • 1,029
  • 6
  • 10
  • Thank You. This helped me tremendously. – Clark Bell Sep 19 '16 at 02:35
  • Before starting with pointers, OP should get the basics right. Which means working through a structured tutorial, resp. book (most online-tutorials are not worth the time). – too honest for this site Sep 19 '16 at 02:41
  • 3
    A couple of nits: the reason to use `%p` is that a pointer might not be the same size as an `int` in some compiler (often, `int` is 32 bits for 64-bit code). You do need to cast an `int*` to `void*` or `char*` when calling a function such as `printf()` with a variable number of arguments, or else you get undefined behavior. An `int*` is not *required* to be as wide as a `void*`! (OP, don’t worry about that yet. I’m language-lawyering.) – Davislor Sep 19 '16 at 02:53
  • The `void *` cast is necessary in portable code. Your last paragraph counteracts the previous paragraph. – M.M Sep 19 '16 at 03:48
  • @Lorehead: Actually `%p` requires a `void *`, not a `char *` (it never had). – too honest for this site Sep 19 '16 at 17:03
  • @Olaf The standard does say that a `char *` (or `unsigned char *`) does not cause UB, though. As you know, a lot of legacy code uses `char *` in place of `void *` for arbitrary objects. However, we should use `void *` today. – Davislor Sep 19 '16 at 19:41
  • @Lorehead: I did not say it does not work. That's actually because of that legacy using `char *` as the universal pointer. Still the standard is very clear about `%p` expecting a `void *`. A beginner should always learn to write standard compliant code. Telling him anything else is a bad idea and just results in confusion. – too honest for this site Sep 19 '16 at 20:21
  • @Olaf: I take your point. Jonathan Leffler: good question, and you should basically ignore the language lawyering here. C is a language with a long history of kludges that still have to work. But get in the habit of writing good code, and you’ll save yourself a lot of trouble. :) – Davislor Sep 19 '16 at 20:32
  • @Lorehead I appreciate the bit of "language lawyering." I learned something new! – GandhiGandhi Sep 21 '16 at 01:16
  • 1
    @GandhiGandhi Thanks. My advice would be: the kind of language lawyering to pay attention to is not, “Does this clever kludge technically work?” but, “Are the assumptions I’m making going to be valid in the future?” A lot of code broke in the 32-to-64-bit transition because programmers assumed `long int` was both exactly 32 bits wide and the size of a pointer, offset, index, timestamp, network address, etc. – Davislor Sep 21 '16 at 02:42
0

In this particular context symbol '&' effectively substitutes any variable following it with the address of the variable.

Victor Havin
  • 1,023
  • 7
  • 11
  • From a test I wrote in C++, and another in C, the inclusion of "&" in a print like statement always seems to print the address. Is this correct? Is there any instance where the inclusion of "&" would not give the address to the variable? – Clark Bell Sep 19 '16 at 02:27
  • In C++ symbol '&' in a function argument declaration indicates that the argument is passed by reference rather than by value. – Victor Havin Sep 19 '16 at 02:38
  • @VictorHavin: The question is about C, not C++. They are different languages, but. `&` does not substitute anything (the concept of substitution is not even part of the core-language, except for the preprocessor). – too honest for this site Sep 19 '16 at 02:43
  • @VictorHavin: The compiler generates code which takes the address of the lvalue, exactly like for e.g. `~` or the binary expression `a + b`. It does not "substitute" anything. One could argue though that it might substitute a _constant-expression_ with the final result in the generated code. But that is an implementation detail, not covered by the standard. And it does not apply here, because the address is not known at compile-time. – too honest for this site Sep 19 '16 at 12:31
  • There are only two mentinings of "substitute" in the standard, but about macro argument substitution which is a textual replacement, making that term clearly wrong when it comes to the next stages. For expressions, "evaluation" is used. – too honest for this site Sep 19 '16 at 12:35
  • @Olaf: This is from Kernigan/Ritchie C Book: "The unary operator & gives the address of an object, so the statement p = &c assigns the address of to the variable p". Now, in English, when instead of assigning value, we assign address, we call it "Substitute value with address". – Victor Havin Sep 19 '16 at 15:36
  • @Olaf: "Because address is not known at compile-time (sic)". Compiler doesn't have to know the address. It simply generates processor instructions to compute it. Most processors have instructions for computing effective address of an operand. For example, when you compile something like p = &c on x86, compiler generates the following instructions: lea eax, [c] followed by mov dword ptr [p], eax. As the result, you will have address of variable c stored in the variable p. – Victor Havin Sep 19 '16 at 16:21