With a C compiler, are array elements are stored in column major order or row major order, or it is compiler dependent?
int arr[2][3]={1,2,3,4,5,6};
int array[3][2]={1,2,3,4,5,6};
on printing arr and array output:
arr:
1 2 3
4 5 6
array:
1 2
3 4
5 6
It seems its always prefer row major order?
Row major order is mandated by the standard.
6.5.2.1p3:
Successive subscript operators designate an element of a
multidimensional array object. If E is an n-dimensional array (n >= 2)
with dimensions i x j x . . . x k, then E (used as other than an
lvalue) is converted to a pointer to an (n - 1)-dimensional array with
dimensions j x . . . x k. If the unary * operator is applied to this
pointer explicitly, or implicitly as a result of subscripting, the
result is the referenced (n - 1)-dimensional array, which itself is
converted into a pointer if used as other than an lvalue. It follows
from this that arrays are stored in row-major order (last subscript
varies fastest).
(Emphasis mine)
You printed the array. The output is in whatever order that you printed the array elements. So what you see has nothing to do with the order in which array elements are stored in memory.
int arr[2][3] means that you have three arrays, and the object stored in each array is an int[2]. Objects are always stored consecutively, so the first int[2] is stored in consecutive memory, followed by the second int[2], followed by the third int[2]. And that is the same for any C implementation.
Related
I have this code, I'm trying to figure out what the second line of code does.
static int table [][4]= {{1,2,3,4},{2,3,4,5},{3,4,5,6}};
int valore = *(*(table+2)+1);
printf("%d",valore);
I have a basic knowledge of pointers in C, can you explain me what does the second line of code do please?
Your table is simply a 2D array of integers. In C a 2D array is really an "array or arrays". Your table has the dimensions of static in table[3][4]; (3 rows x 4 cols), it is an array of 3 integer arrays with 4 elements each. Since it is an array, all values will be sequential in memory. You can think of the memory layout as follows.
+---+---+---+---+
table[0] | 1 | 2 | 3 | 4 |
+---+---+---+---+
table[1] | 2 | 3 | 4 | 5 |
+---+---+---+---+
table[2] | 3 | 4 | 5 | 6 |
+---+---+---+---+
An array is converted to a pointer on access (accept in 4 limited circumstances, not relevant here, see C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) for details)
You are introduced to "pointer notation" in the question. You can access any element of an array using "array indexes" or "pointer notation". In pointer notation *(a + b) is equivalent to a[b] in array index notation. You have:
*(*(table+2)+1)
If you take it piece by piece *(table + 2) is simply table[2]. Next *(table[2] + 1) is simply table[2][1]. So you are acccessing the 2nd value in the 3rd row with either (which is simply 4).
Look things over and let me know if you have further questions.
table is an array of 3 arrays of 4 int.
When an array is used in an expression, it is converted to a pointer to its first element, except when:
It is the operand of sizeof.
It is the operand of unary &.
It is a string literal used to initialize an array.
So, in *(*(table+2)+1), table is converted to a pointer to its first element, producing &table[0]. Then we have:
*(*(&table[0]+2)+1)
Next, we have the addition &table[0] + 2. This uses pointer arithmetic. Adding an integer to a pointer (into an array) moves the pointer backward or forward by a number of elements. So &table[0] + 2 produces a pointer to table[2], which is &table[2]. Then we have:
*(*(&table[2])+1)
The inner parentheses are no longer needed, so we have:
*(*&table[2]+1)
Then * &table[2] is the thing that &table[2] points to, which means it is table[2]:
*(table[2] + 1)
Since table is an array of 3 arrays of 4 int, table[2] is an array of 4 int. Since it is an array, it is converted to a pointer to its first element, producing &table[2][0]:
*(&table[2][0] + 1)
Now we have pointer arithmetic again. &table[2][0] is a pointer to element 0 of the array table[2], so adding 1 produces a pointer to element 1, &table[2][1]:
*(&table[2][1])
Again we have parentheses that are no longer needed:
*&table[2][1]
And, finally, * &table[2][1] is the thing that &table[2][1] points to, so it is just:
table[2][1]
I have an issue with the multidimensional arrays. Maybe the solution is much easier.
int arr[2][2]; //multidimensional array
My simple question is: why the
arr[0][2] and arr[1][0]
or
arr[1][2] and arr[2][0]
are on the same address in my case?
I checked this problem in Linux and Windows environment. And the issue is the same. I have checked tutorials and other sources, but no answer.
The pointer &arr[0][2] is the one-past-the-end pointer of the array arr[0]. This is the same address as that of the first element of the next array, arr[1], which is &arr[1][0], because arrays are laid out contiguously in memory.
arr[2][0] is a bit tricker: arr[2] is not a valid access, but &arr[2] is the one-past-the-end pointer of the array arr. But since that pointer cannot be dereferenced, it doesn't make sense to talk about arr[2][0]. arr doesn't have a third element.
C stores multi-dimensional arrays in what is called row-major order. In that configuration, all the data for a single row is stored in consecutive memory:
arr[2][2] -> r0c0, r0c1, r1c0, r1c2
The alternative would be column-major order, which places the columns consecutively.
Since you have specified the length of the row (number of cols) as 2, it follows that accessing column 2 (the third column) will compute an address that "wraps around" to the next row.
The math looks like:
&(arr[row][col])
= arr # base address
+ row * ncols * sizeof(element)
+ col * sizeof(element)
= arr + sizeof(element) * (row * ncols + col)
In your case, arr[0][2] is arr + (0*2 + 2) * sizeof(int), while arr[1][0] is arr + (1*2 + 0)*sizeof(int).
You can do similar math for the other variations.
Array indexing is identical to pointer arithmetic (actually, the array name first is converted ("decays") to a pointer to the first element before the []-operator is applied):
arr[r][c] <=> *(arr + r * INNER_LENGTH + c)
Your array has two entries per dimension. In C indexes start from 0, so for each dimension valid indexes are 0 and 1 (i.e. total_entries - 1). Which makes three of your expressions suspective in the first place:
arr[0][2] // [outer dimension/index][inner dimension/index]
arr[1][2]
arr[2][0]
We have these cases:
Both indexes are valid: no problem.
Only the address is taken, the element is not accessed and
the outer index is valid and the inner (see below) index equals the length of the inner dimension: comparison and certain address arithmetic is allowed (other constraints apply!).
the outer index equals the length of the outer dimension, and the inner index is 0: The same.
Anything else: the address is invalid and any usage (take address, dereference, etc.) invokes undefined behaviour.
What exactly goes on in memory might become a bit more clear if we use different lengths for the dimensions and have a look how the data is stored:
int arr[3][2];
This is an "array of 3 arrays of 2 int elements". The leftmost dimension is called the "outer", the rightmost the "inner" dimension, because of the memory layout:
arr[0][0] // row 0, column 0
arr[0][1] // row 0, column 1
arr[1][0] // ...
arr[1][1]
arr[2][0]
arr[2][1]
Using the formula above, &arr[0][2] (arr + 0 * 2 + 2) will yield the same as &arr[1][0] (arr + 1 * 2 + 0), etc. Note, however, while the addresses are identical, the first version must not be dereferenced and the compiler may generate incorrect code, etc.
Array indexing in C is similar to adding the value of the index to the address of the first element.
In the multidimensional array that you describe, you have 2 elements on each dimension: 0 and 1. When you introduce a number larger than that, you're referencing an element outside that dimension. Technically, this is an array out of bounds error.
The addresses break down like this:
arr[0][0] - &arr[0] + 0
arr[0][1] - &arr[0] + 1
arr[1][0] - &arr[0] + 2
arr[1][0] - &arr[0] + 3
When you write arr[0][2], you're referencing address &arr[0] + 2, which is the same as arr[1][0]. It all just pointer math, so you can work it out pretty easily once you know how it works.
You can look in your two dimensional array as a long one dimensional array:
[00][01][10][11]
With the pointers arithmetic, another representation of this long one dimensional array is:
[00][01][02][03]
So looking in cell [10] is exactly the same as looking into a cell [20] in pointer arithmetic point of view.
What is the difference between $size and $bits operator in verilog.?
if I've variables, [9:0]a,[6:0]b,[31:0]c.
c <= [($size(a)+$size(b)-1]-:$bits(b)];
What will be the output at 'c' from the above expression?
$size() gives the number of bits for a single dimension. $bits() gives the number of bits to completely represent the variable.
For example:
reg [9:0] a;
reg [9:0] b [5:0];
initial begin
$display("a Size ", $size(a));
$display("a Bits ", $bits(a));
$display("b Size ", $size(b));
$display("b Bits ", $bits(b)) ;
end
Gives :
a Size 10
a Bits 10
b Size 6 // Depth of memory
b Bits 60 // Width * Depth
In your case you just have 1 dimensional arrays, not memories or structs so $size() and $bits() would be the same thing.
$size shall return the number of elements in the dimension, which is equivalent to $high - $low + 1. It is relative to the dimension, not only bit counts. If the type is 1D packed array or integral type, it is equal to $bits.
$bits system function returns the number of bits required to hold an expression as a bit stream.
$bits ( [expression|type_identifier] )
It returns 0 when called with a dynamically sized type that is currently empty. It is an error to use the $bits system function directly with a dynamically sized type identifier.
I have no idea about your question, c <= [($size(a)+$size(b)-1]-:$bits(b)];. Is it a valid expression in RHS? Are you talking about the array range expression, [n +: m] or [n -: m] ?
In 3["XoePhoenix"], array index is of type array of characters. Can we do this in C? Isn't it true that an array index must be an integer?
What does 3["XeoPhoenix"] mean?
3["XoePhoenix"] is the same as "XoePhoenix"[3], so it will evaluate to the char 'P'.
The array syntax in C is not more than a different way of writing *( x + y ), where x and y are the sub expressions before and inside the brackets. Due to the commutativity of the addition these sub expressions can be exchanged without changing the meaning of the expression.
So 3["XeoPhoenix"] is compiled as *( 3 + "XeoPhoenix" ) where the string decays to a pointer and 3 is added to this pointer which in turn results in a pointer to the 4th char in the string. The * dereferences this pointer and so this expression evaluates to 'P'.
"XeoPhoenix"[ 3 ] would be compiled as *( "XeoPhoenix" + 3 ) and you can see that would lead to the same result.
3["XeoPhoenix"] is equivalent to "XeoPhoenix"[3] and would evaluate to the 4th character i.e 'P'.
In general a[i] and i[a] are equivalent.
a[i] = *(a + i) = *(i + a) = i[a]
In C, arrays are very simple data structures with consecutive blocks of memory. They therefore need to be integers as these indices are nothing more than offsets to addresses in memory.
How do addresses get generated in arrays in C, say how does a [x][y] get to a particular value, i know its not that big a question but just about to actually start coding.
Well it is done depending on your data type of whose array you have considered.
Say for an Integer array, each value holds 4 bytes, thus a row X long will take 4X bytes.
Thus a 2-D matrix of X*Y will be of 4*X*Y Bytes.
Any address say Arry[X][Y] would be
calculated as : (Base Address of Arry)
+ (X * No. of columns) + ( Y // Offset in current row )
2-dimensional arrays in C are rectangular. For example:
int matrix[2][3];
allocates a single block of memory 2*3*sizeof(int) bytes in size. Addressing matrix[0][1] is just a matter of adding 0 * (3 * sizeof(int)) to sizeof(int). Then add that sum to the address at which matrix starts.
A nested array is an array of arrays.
For example, an int[][6] is an array of int[6].
Assuming a 4-byte int, each element in the outer array is 6 * 4 = 24 bytes wide.
Therefore, arr[4] gets the third array in the outer array, or *(arr + 4 * 24).
arr[4] is a normal int[]. arr[4][2] gets the second int in this inner array, or *(arr + 4 * 24 + 2 * 4)
E.g.
char anArray[][13]={"Hello World!","February","John"};
You can visualize it as:
anArray:
H|e|l|l|o| |W|o|r|l|d|!|\0|F|e|b|r|u|a|r|y|\0|\0|\0|\0|\0|J|o|h|n|\0|\0|\0|0|\0
^ ^ ^
0 13 26