answersLogoWhite

0

Array variables are essential because an array is nothing more than a contiguous allocation of memory and we need some way to refer to both the memory itself and the objects within that memory. For that reason, array variables don't behave like ordinary variables:

int x {42};

int y[10] {42};

In the above example, we've declared a single integer variable named x and an array of 10 integers named y. We've initialised both variables with the value 42 (the remaining 9 elements of y will be default initialised with the value 0).

Both x and y are named variables, however x refers to an actual value (of type int) whereas y refers to the address of a value (of type int). We can see the difference if we print the address and value of each variable:

printf ("Address of x: 0x%08x\n", &x);

printf ("Value of x: %d\n", x);

printf ("Address of y: 0x%08x\n", &y);

printf ("Value of y: %d\n", y);

Possible output:

Address of x: 0x00e19000

Value of x: 42

Address of y: 0x00e19004

Value of y: 14782468

Note that the value of y is not 42 as you might expect. Here, 14,782,468 is the decimal equivalent of 0x00e19004, which is the address of y (in hexadecimal). Both y and &y refer to the start address of the array, so y is not a variable at all, it is a reference!

For every array a and integer j within the range of a, we have the following equivalences:

a[j] j[a]

It often surprises people to find that 3["abcde"] 'c', however we should never use these equivalences in production code. They are much too low-level and do not hold for higher-level containers such as the std::array and std::vector standard-library containers in C++. However, it's important that we fully understand why array variables are not variables in the normal sense.

For any array a of type T, the equivalence at the machine-level can be expressed as follows:

assert (a[j] == *(a + (j * sizeof (T))));

Given that a is a reference rather than a variable, the array subscript operator [] gives the programmer an intuitive and convenient means of performing pointer arithmetic upon that reference. Moreover, we can apply the exact same notation to pointer variables:

T* p = &a;

assert (p[j] == *(p + (j * sizeof (T)));

Functions that operate upon arrays cannot differentiate between a fixed-length array and a variable-length array:

void scale (int x[10], int scalar) {

for (int i=0; i<10; ++i) x[i] *= scalar;

}

int y[5] {1, 2, 3, 4, 5};

scale (y, 2); // trouble awaits!

Although the function appears to expect an array of exactly 10 elements, int[10] is not a type. The actual type is int* (a reference to the start address of the array), thus the compiler interprets the function as if it were actually written as follows:

void scale (int* x, int scalar) {

for (int i=0; i<10; ++i) x[i] *= scalar;

}

The function is hardwired with the magic number 10, but the function cannot know if x really refers to an array of 10 elements because all size information is lost. When we pass y to this function, the compiler will not complain, but y only has 5 elements, so there's a risk of overwriting memory that doesn't belong to our program. Technically, the function has undefined behaviour.

To fix the problem we must pass the length of the array as well as the start address, and eliminate the magic number 10 entirely:

void scale (int* x, size_t len, int scalar) {

for (int i=0; i<len; ++i) x[i] *= scalar;

}

int y[5];

scale (y, 5, 2); // ok!

Confusingly, although int[10] is not a type, int[][10] is treated as if it really were a type (one of the many inconsistencies in C). Thus the following is perfectly valid:

void scale (int x[][10], size_t len, int scalar) {

for (int i=0; i<len; ++i)

for (int j=0; j<10; ++j)

x[i][j] *= scalar;

}

In this example, x is a multi-dimensional array which decays to int** rather than int*. The additional level of indirection is necessary because every element in the array named x is of type int[10], which is yet another array (and therefore not a type!). As before, it's best to eliminate the magic number 10 entirely and pass the extra dimension through another argument. However, the compiler won't accept int x[][] as a valid type. The solution is to use the following form:

void scale (int* x[], size_t len1, size_t len2, int scalar) {

for (int i=0; i<len1; ++i)

for (int j=0; j<len2; ++j)

x[i][j] *= scalar;

}

The compiler will interpret this as if it were actually written:

void scale (int** x, size_t len1, size_t len2, int scalar) {

for (int i=0; i<len1; ++i)

for (int j=0; j<len2; ++j)

x[i][j] *= scalar;

}

The latter form is the preferred form as the indirection makes it much clearer how many dimensions we're actually dealing with. The variables len1 and len2 would normally be named rows and columns respectively, as we normally imagine a two-dimensional array as being a matrix or table of rows and columns. C uses row-major order, thus the first dimension always specifies the number of rows, and the second tells us how many elements of the given type (int) are in each row. Thus x[i] refers to the ith row of x, while x[i][j] refers to the jth element of the ith row of x (where i and j are both zero-based indices).

User Avatar

Wiki User

8y ago

What else can I help you with?

Related Questions

What is the need of array variables?

congugative memory allocation ,is use to array


What are Array variables also called as?

Elements of the array.


Simple non-array variables are usually passed to methods by?

Simple non-array variables are usually passed to methods by value.


What is array indexing?

Unlike ordinary variables, the variables within an array do not have any names; they are anonymous. To access them you need to use memory offsets from the start of the array. Since the elements of an array are all the same type they are also the same length, thus the offsets are equal to the length of the array type. However, there is no need to calculate the offsets because each element's offset has a zero-based index. Thus the second element can be found at offset index 1.


Why object array called universal array?

Object array is called universal array because it can store multiple variables of the same type


Full defecation of array?

Full representation of an array begins from the index 0 and ends at n-1 where n is the number of variables of the array.


Do you use an array when you only have two or three items to track?

Yes. Using an array when multiple elements need to be created at a time is always a better idea than declaring multiple variables. For ex: Int i, j, k; Int[] arr; I have declared 3 int variables and another array just below it. Here since we are using only 3 variables, we can manage to use them without issues but if the number crosses 5 or even more then definitely using an array is always the best option.


When an array is declared does c automatically initializes its elements to zero?

For global/static variables: yes.For auto variables: no.


Can you give an example of array using character variable in c program?

the example of array over charcter variables is char ["string"]


What does the word array mean in math?

An array is a set of numbers that form some sort of regular arrangement. A linear array is a 1-dimensional array consisting of a row or a column of a set of numbers. A 2-dimensional array is a rectangular arrangement of numbers. And there are arrays with higher dimensions. The elements of an array need not be numbers: they could be variables, functions or expressions. In other words, it's a picture to describe a multiplication problem.


How many structure variables of a given type can you use in a C program?

You can use unlimited number of variables for a structure and you can also declare array of structures.


What is the importance of array?

Arrays are important because we often need to work with a collection of variables of the same type and, particularly with large collections, it would be impractical to declare and name each one individually. With an array we don't have to name them because the variables are allocated in contiguous memory addresses and every element is the same length. Knowing only the start address of the array and the zero-based index of an element we gain constant-time random access to any element in the array. An array is really just an extension of a type. When we declare a variable of a given type we allocate sufficient memory to hold just one object of that type. With an array, we can allocate as many objects as we require.