6

I am reading up on c# arrays so my question is initially on arrays.

What does declaring an array actually mean? I know you declare a variable of type array. When I have the following, what is actually happening?

int[] values;

Is it in memory by the time it is declared? If not then where is it? Is the array actually created here?

Then I go and instantiate an the array and initialise it with some values like:

int[] values = new int[] { 1, 2, 3 };

Does this actually go and create the array now? I have read that arrays are created when they are declared, others say that arrays are created when they are instantiated. I am trying to get my terminology right.

The same goes for an integer variable. If I have:

int value;

and

int value = 1;

When is int created? When is it added to memory?

Sorry for the dumb questions. I understand the concept but would like to know the technicallity behind the scenes of arrays.

Brendan Vogt
  • 25,678
  • 37
  • 146
  • 234

4 Answers4

6

What does declaring an array actually mean?

You didn't actually declare an array, you declared an array reference. Big deal in .NET, the difference between reference types and value types is important. Just having the array reference variable isn't enough, an extra step is required to create the array object. Which requires the new keyword. Which physically allocates the storage for the array object in the place where reference type objects are stored, the garbage collected heap.

The same goes for an integer variable

No, big difference. That's a value type. If it isn't a field of a class, not that clear from your question, then it is a local variable of a method. It gets created when the method starts running and poofs out of existence when the method returns. Very highly optimized, the core reason that value types exist in C#. The physical storage location is typically a cpu register or a slot on the stack frame if the method uses too many local variables.

If it is actually a member of a class then it gets created when the class object gets created. Just like an array, on the GC heap with the new keyword.

Servy
  • 202,030
  • 26
  • 332
  • 449
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    If you take it literally, the `new` keyword is not required to create an array object, you can also write something like `int[] values = { 1, 2, 3 };`. Though you could consider that to be just a shortcut for the full syntax with `new`. – svick Jul 11 '13 at 18:46
  • @Hans: Does declaring an array reference take up any memory? Or only when the array is created? – Brendan Vogt Jul 12 '13 at 11:24
  • It does, the size of a pointer. 4 bytes in 32-bit process, 8 bytes in a 64-bit process. Storage for the reference follows the same rules as those for a value type value. – Hans Passant Jul 12 '13 at 11:27
1
int[] values;

Means that you declare a variable of type int[]. No memory is occupied yet, only a reference is created. The code above is initialized to a null-reference.

int[] values = new int[] { 1, 2, 3 };

This code declares a variable of type int[], and immediately creates an array. The variable references the newly created array.

Integers work a little different since they are value-types. Value types are initialized to their default values, in case of integers, the value 0.

If you split the declaration and the initialization, the following happens.

// This declares a variable
int[] values;
// This creates the array, and initializes the variable with the newly created array.
values = new int[] { 1, 2, 3 };
Maarten
  • 22,527
  • 3
  • 47
  • 68
  • 1
    You only create a null reference for `int[]` if it's a member of a type, and when an instance of that type is created. If you do that inside a method you don't even have a reference until you initialize it. – Geeky Guy Jul 11 '13 at 12:15
  • @Renan I'm not sure what you mean. The null reference is not a member of any type (http://ericlippert.com/2013/05/30/what-the-meaning-of-is-is/). – Maarten Jul 11 '13 at 12:32
  • “No memory is occupied yet, only a reference is created.” Are you saying a reference doesn't occupy any memory? – svick Jul 11 '13 at 18:54
  • @Maarten I think Renan is trying to say that you can't for example do `int[] values; Console.Write(values);`. You can't access uninitialized local variable, so it doesn't make sense to talk about its default value. – svick Jul 11 '13 at 18:56
  • @svick No, what I meant is that the object (in this case an array-of-ints) is not yet created. The reference itself (in this case, a null reference) is created, and does occupy memory (a reference is an Int32 on 32 bits systems I thought). – Maarten Jul 12 '13 at 06:15
  • It's initialized to a null reference if it's a class member. A local variable of type `int[]` declared as `int[] values;` is treated as uninitialized in C#, and the compiler won't let you inspect the reference until you assign it. One may of course right `int[] values = null;` which explicitly initializes the reference. – Ben Voigt Jul 16 '13 at 01:46
1

When you declare an array, internally all that is being created is a null pointer that is of type int[]. When you use the new keyword as in your example, or you use new int[6], at that time the system allocates memory for the size of the array.

Declaring an int will actually create the memory for the integer with default value of 0.

Samuel
  • 16,923
  • 6
  • 62
  • 75
  • 1
    C# behaves the same, since `int` is a value type, see here: http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx. Quote: *Unlike reference types, a value type cannot contain the null value. (...) Each value type has an implicit default constructor that initializes the default value of that type.* – Treb Jul 11 '13 at 11:56
  • Your second paragraph is incorrect. int is a value type that defaults to zero. Try this: `void Main(){Console.WriteLine(new X().i);}class X{public int i;}` – spender Jul 11 '13 at 11:57
  • Thanks for the correction. I thought I read somewhere that `int` was an alias for `Int32` or something. – Samuel Jul 11 '13 at 12:13
  • 3
    @Samuel `int` *is* an alias for `Int32`. But `Int32` is a value type, which is totally different from Java's `Integer`. – svick Jul 11 '13 at 18:50
1

When you declare it like this:

int[] values;

you don't specify the size, so there is no way to know how much memory would be needed for an instatiation. This information is only given in the following line:

values = new int[] { 1, 2, 3 };

The memory requirements are deduced from the number of instatiation values (and from the memory requirements of the type int, of course).

When you declare an int like this:

int value;

the memory requirements are known and cannot change (since int is a value type). This variable can (and will) be created immediately. If you don't specify an initial value, it will have it's default value, which for int is 0.

Treb
  • 19,903
  • 7
  • 54
  • 87
  • Are you saying that if you write just `int[] values`, then the memory for that *variable* is not allocated? That's wrong, because that variable contains a reference and the memory for that *is* allocated. – svick Jul 11 '13 at 18:53
  • Also, it doesn't make sense to talk about default values of local variables, they don't have any. For example, you can't write `int i; Console.WriteLine(i);`. – svick Jul 11 '13 at 18:54
  • @svick: Your comment number 1: I didn't express myself clearly enough, I meant that the memory **for the array** isn't allocated. Your comment number 2: `int`, like all value types, *has* a default value. The C# compiler doesn't allow you to use a variable **you** haven't initialized before, that is correct. But the `i` in your example is **automatically** initialized to it's default value, i.e. 0. You can for example check this in the debugger. Replace `Console.WriteLine(i);` with `Console.WriteLine("bla");`, set a breakpoint on that line and inspect `i`, you will see that it's value is 0. – Treb Jul 12 '13 at 07:16
  • Still, it doesn't make sense to talk about the default value if you can't access it. And are you sure you would get the same behavior in the debugger with all optimizations enabled? – svick Jul 12 '13 at 09:43
  • @svick: I'm not certain, but I believe the *must initialize before use* is a C# specific feature, not something enforced by the CLI. So I expect the behaviour to be the same with optimizations. You're right about the default value being practically irrelevant. But since most of the answers here are in "hair splitting mode", I think that detail with the default value has it's place here ;-) – Treb Jul 15 '13 at 07:31