I know that \'mutable\' and \'immutable\' are terms that should be used to describe the ability for objects to change value in object oriented languages such as Java and Obj
The best way to understand how C works is to think of it as high-level assembly language. Variables are simply locations in memory, and assigning a value to a variable stores the value into that location. From a high-level language perspective, that would be mutation in its purest form.
In C, a declaration/definition like
int x;
tells the compiler to reserve some memory for the int
variable x
. (Inside a function, the memory would come from the stack. At global scope, it would come from the data segment.)
An assignment like
x = 7;
simply generates code to copy the value 7 into that memory location. Similarly, an assignment like
x = y;
generates code to copy the int
value stored at y
's memory location into x
's memory location. (Assume y
is another int
.)
The same logic also holds for more complex types than int
s.
In Java, variables are references instead (for non-primitive types anyway), and can refer to different objects at different times. To get something similar to references in C, you have to explicitly define a pointer variable -- a variable that holds an address -- and point it to (assign it the address of) different objects at different times.
(I included the below example just in case you're interested.)
The &
operator is used to get the address of a variable in C, so that &x
would be the address of x
for example. The *
operator gives the pointed-to object when applied to a pointer. Here's an example of how a pointer could be used to refer to different variables at different times:
int x;
int y;
/* Declares 'ptr' as a pointer, and says that it points to an int.
The pointed-to type is used by the compiler for type checking
and type conversions. */
int *ptr;
ptr = &x; // Store the address of 'x' in 'ptr'.
*ptr = 1; // Store 1 into the memory 'ptr' points to ('x').
ptr = &y; // Store the address of 'y' in 'ptr'.
*ptr = 2; // Store 2 into the memory 'ptr' points to ('y').
The end result of the above code would be to set x
to 1 and y
to 2. This is a silly example of course, but hopefully it should get the idea across.
(C99 and later support //
-style comments by the way.)
(Caveat: My Java is a bit rusty, so I had to do some reading up. Hopefully the details should be correct. Feel free to correct me.)
The assignment
x = "Goodbye World";
would have the effect of making x
refer to a String
object with the value "Goodbye world". Exactly when this String
object is created shouldn't make a difference, as long as it's created before it's assigned to x
(or any other variable).
It might be created just before the assignment is executed, or when the program starts. Normally you wouldn't be able to tell the difference.
It sounds like you have the high-level concepts down, and your C code is correct.
(It's more correct to say that "ptr
is a pointer" than to say that "*ptr
is a pointer" though. There's some syntactic obscurity in C that makes it more natural to put the *
next the name in the declaration (IMO), but you can also write the declaration like int* ptr;
for that case. Things only start to get weird when you declare many variables in the same line.)
When talking about how Java is implemented, references might have to be a bit more advanced than just pointers to objects under the hood. For example, the JVM might move objects around in memory (which would change their address) to reduce memory fragmentation, but references must still remain valid. One way to do it would be to "fix" pointers whenever objects are moved, another to have references be indices into a table of pointers instead. Regardless of how it's done in the JVM implementation, pointer is the right thinking at least.
Since each reference in Java has a pointer field (at a high level, ignoring exactly how the implementation does it), and since this field isn't needed for primitive types, one possibility is to reuse the pointer field and store the value in it instead for primitive types.
For example, an assignment like
x = 1;
might store the value 1 directly into the pointer field of the reference x
. Techniques like this are pretty common.
As a side note, a union
can be used to in C to store two different types (e.g., an int
and a pointer) in the same place in memory so that they overlap. Of course, assigning to one of the types would change the value for the other type too.
It should be the current primitive modified. I tested using a simple code here, and it refers to the same address.
#include <stdio.h>
int main(void) {
// your code goes here
int a = 5;
printf ("%p = %i\n", (void*) &a, a);
a = 10;
printf ("%p = %i\n", (void*) &a, a);
return 0;
}