Im reading over some code on github trying to understand what its doing.
I came across this:
for (int k = 0; k < N/GROUP_SIZE; k++) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < GROUP_SIZE; j++) {
tempB[i][j] = *(B+k*GROUP_SIZE+i*N+j);
}
}
B is a one dimensional array of size (N*N)
tempB is a two dimensional array of size [N][GROUP_SIZE]
Im quite unsure what this line does though:
tempB[i][j] = *(B+k*GROUP_SIZE+i*B_WIDTH+j);
Does it access only part of the array?
I would try to google this question, but im not sure what to call the operation
temp[i][j] = accesses one cell of a multi-dimensional array and places the value into it.
As for *(B+k*GROUP_SIZE+i*B_WIDTH+j), here B is the name of an array, which is also a pointer to the first element of that array.
*(B + a) is equivalent to B[a]. B + 1 would point to the second element of that array, and B + 2 to the second element. * operator dereferences the pointer, and returning value at that index.
Related
If you have a function that takes the pointer of an array, would there be any use in using pointers to each element in the array, or is it redundant? For example:
int sum(int(*arr)[3]) {
int i,j, sum = 0;
for (i =0; i < ROW ; i ++) {
for (j =0; j < COL ; j ++) {
sum = sum + *(*( arr +i )+j);
}
}
}
Would using arr[i][j] be the same in this case?
arr[i] is required by the standard to be equivalent to *(arr + i) so no, there is no point in not using arr[i] which is more readable.
Speeding up 2d array access is a complex topic. There are some techniques for performance improvement, but those take hardware architecture (e.g. cache) into account are are related to access patterns rather than access syntax.
I was working on the following 2d-array program to output this result shown in picture:
I can't seem to get the min value for the result and get it displayed in array form.
The code is below:
#include<stdio.h>
#define NUMROWS 2
#define NUMCOLS 3
//accessing elements of 2D array using pointers
int main(void){
const int table[NUMROWS][NUMCOLS]={{1,2,3},{5,6,7}};
int minvals[NUMROWS];
int i, j;
int *ptr = &table;
//accessing the elements of 2D array using ptr
printf("table values: min value\n");
for(int i=0;i<NUMROWS;i++){
for(int j=0;j<NUMCOLS;j++)
printf("%d ",*((ptr+i*NUMCOLS)+j));
printf("\n");
}
for(int i=0;i<NUMROWS;i++){
for(int j=0;j<NUMCOLS;j++)
printf("%d ",*((ptr+i*NUMCOLS)+j)<minvals[i]);
}
return 0;
}
The existence of minvals would imply that you are expected to calculate the minimum value of each 'row' of table before then moving on to printing. As it stands, had your program properly calculated the minimum values of each array, your printing would be rather out of order.
There's no need to do any tricky, manual pointer manipulation. Simple array subscription is much clearer.
Let's start simple and return to basics by looking at the way we find the minimum value in a one dimensional array, as it is the core of this problem.
To find the minimum value in an array we need a few things to start:
An array
The length of the array
An initial value to compare against
The array itself is obviously each subarray of table, and the length in this case is known to be NUMCOLS. Our initial value should either be INT_MAX (or another type-appropriate maximum constant found <limits.h>), such that every element in the array is equal to or less than our initial value, or a value from the array itself.
Often times we opt for the second option here, choosing the first element in the array as our initial value, and comparing it to the second and onward elements.
As such, finding the minimum value in a single 'row' would look like this
const int row[NUMCOLS] = { 9, 2, 5 };
int min = row[0];
for (int i = 1; i < NUMCOLS; i++)
if (row[i] < min)
min = row[i];
but since we want to find and record the minimum value of each 'row' in table, we're going to use a nested loop. Instead of the min variable from before, we store each value in the associated index of our minvals array.
for (i = 0; i < NUMROWS; i++) {
minvals[i] = table[i][0];
for (j = 1; j < NUMCOLS; j++)
if (table[i][j] < minvals[i])
minvals[i] = table[i][j];
}
When it comes time to print, we're going to repeat our nested loop. Our inner loop prints each element of each 'row' of table, and we end each iteration of the outer loop by printing the value found in minvals with the same index of our 'row'.
for (i = 0; i < NUMROWS; i++) {
for (j = 0; j < NUMCOLS; j++)
printf("%6d", table[i][j]);
printf(":%6d\n", minvals[i]);
}
Here's a working example.
#include <stdio.h>
#define NUMROWS 2
#define NUMCOLS 3
int main(void) {
const int table[NUMROWS][NUMCOLS] = {
{ 9, 2, 5 },
{ 3, -4, -12 }
};
int minvals[NUMROWS];
int i, j;
for (i = 0; i < NUMROWS; i++) {
minvals[i] = table[i][0];
for (j = 1; j < NUMCOLS; j++)
if (table[i][j] < minvals[i])
minvals[i] = table[i][j];
}
puts("Table value: minimum values");
for (i = 0; i < NUMROWS; i++) {
for (j = 0; j < NUMCOLS; j++)
printf("%6d", table[i][j]);
printf(":%6d\n", minvals[i]);
}
}
A good further exercise for you would be to compose the logic of the inner loop for finding minimum values into a more generic function. Its function signature would look like
int min(int *array, size_t length);
allowing it to work on arrays of varying sizes. Then our outer loop could be as simple as:
for (i = 0; i < NUMROWS; i++)
minvals[i] = min(table[i], NUMCOLS);
The line
int *ptr = &table;
is wrong, because &table is of type int (*)[2][3] (i.e. a pointer to the entire table), whereas ptr is a pointer to a single element. Also, your pointer is non-const, so it cannot point be made to point into a const array.
If you want ptr to point to a single int value, then you should declare it the following way:
const int *ptr = &table[0][0];
Also, you are reading the contents of the array minvals, although that array contains uninitialized data. This does not make sense and causes undefined behavior.
Instead of doing complex pointer arithmetic with the expression
*((ptr+i*NUMCOLS)+j))
you can simply write the following:
table[i][j]
That way, you do not need the pointer ptr and your code is simpler.
Here's the code and wondering if you can help me understand it.
/* Two dimensional array */
#include <stdio.h>
void main() {
int i, j, sum[2], mean[2];
int mark[3][2] = { { 34, 56}, { 48, 65}, { 53, 59} };
for (j = 0; j < 2; j++)
sum[j] = 0;
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
sum[j] = sum[j] + mark[i][j];
}
}
for (j = 0; j < 2; j++)
mean[j] = sum[j] / 3;
printf("Average mark in Mathematics is %d\n", mean[0]);
printf("Average mark in Chemistry is %d\n", mean[1]);
}
My understanding of it so far....
Define data types i, j, sum[2], mean[2] as integers.
Initialising the array....mark is data type int, the array should have 3 rows and 2 columns.
First for loop, j initialised at 0, condition: j has to be less than 2, update: add one onto the value of j. Sum of j = 0.
Also for 2nd loop, i initialised at 0, condition: i has to be less than 3, update: add one onto the value of i.
Similar for the next line that uses the for loop and value j.
I'm a bit confused about the syntax:
sum[j] = sum[j] + mark[i] [j]; does this mean, work out the sum of j and add it to the marks contained in the array displayed as [i] and [j].
After this is completed then similar j loop though not sure how this interacts with the previous loops.
Mean calculated and values printed to the screen.
When I've looked at the worked example...
sum[0] = 0 and sum[1] = 0, I don't really understand why sum[1] is also 0.
Firstly, i=0 and j=0,
sum[0] = sum[0] + mark [0,0]
then j=1
sum[1]=sum[1]+mark[0,1]
then
i=1, j=0
sum[0] = sum[0] + mark [1,0]
then
sum[1] = sum[1]+mark[1,1]
then i = 2, j=0
sum [0] = sum[0]+ mark[2,0]
then
sum[1] = sum[1]+ mark[2,1]
What is confusing me a bit is how the loops are interacting with each other and the values of i and j throughout.
I know that the 2d array would be in a table (that I can't seem to format here).
Would appreciate if anyone could shed some light on this.
sum[j] = sum[j] + mark[i][j]; can be simplified as sum[j] += mark[i][j];. It adds the contents of the cell at row i, column j of the 2D matrix mark to the jth element of array sum.
Accessing an element of a 2D array is written mark[i][j] in C, not mark[i, j].
Note that mark[i, j] is not a syntax error: the expression i, j is a comma expression, evaluating i, then discarding it and evaluating j. It is therefore the same as mark[j] which is not a matrix cell but a reference to the jth row of the 2D matrix.
Nope, an array is in fact a pointer (aka an address). When you define int sum[2], sum is the address of the first element of your array of two integer.
So sum is an int* or int[] (same).
Mark is an 2d array. Mark is in fact an array of array. So Mark contain addresses, and thoses addresses are the beggining of some arrays.
(In fact it can be different in the memory, but the compiler do the work).
Mark is a int**, or an address of address of int.
When you do:
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
sum[j] = sum[j] + mark[i][j];
}
}
It's like if you were saying
for each line i in the array, I want to do:
for each value j in the line, I want to do:
...;
Like this, you work on every "line" (or column, visualize the way you want), and for every "line", you work on every value.
I was told that there was a convention when you have a code to print an array, that there is a value that must come first than the other one, for example:
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; column++)
System.out.print("" + array[i][j]);}
Would be i first or it needs to be j first? I find answers like this one but they don't solve my doubt...
PS: I'm not asking just about Java, but about C#, C, C++, Javascript, etc.
The convention is to do it in order, as you have written:
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; column++)
System.out.print("" + array[i][j]);}
Here, i is before j in the loops, and array is indexed by i before j as well.
This is the natural order, as written in the code. It is also the order in which the memory elements are stored in most languages (Java, C#, C, C++). This is called row-major order, where elements in the same row are in contiguous memory locations.
For a 3 by 3 array a[3][3] in row-major order, the elements are stored as:
a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2], a[2][0], a[2][1], a[2][2]
Indexing into the array in row-major order also has performance benefits. By accessing memory sequentially, you minimise cache misses.
for (int i = 0; i < array.length; i++) {
means that i serves as an index for the elements of array (the elements happen to be sub arrays).
for (int j = 0; j < array[i].length; column++)
indicates that j serves as an index for the elements of array[i] (the sub arrays of array).
So yes, i needs to be before j.
error lvalue returned as left operand of assignment
What is the error in this program;
int(*matrix)[row][col];
int i = 0;
if(n == 1)
{
for (int i = 0; i < no_matrices; i++)
{
printf("Matrix %d", i + 1);
(matrix + i) = GetMatrixU(row, col); // (error here)
}
}
int* GetMatrixU(int row, int col)
srand(time(NULL));
int(* matrix)[col] = malloc(col*sizeof(int));
for (int i = 0; i < row; i ++)
{
for (int j = 0; j < col; j ++)
{
matrix[i][j] = rand()%100;
}
}
return matrix[];
}
The problem is this line:
(matrix + i) = GetMatrixU(row, col);
This tries to make an assignment. The expression on the right is evaluated; this is the "r-value" ("r" for "right"). Then the result should be assigned to the expression on the left, which is the "l-value" ("l" for "left").
Well, (matrix + i) is not a valid l-value. matrix by itself is a single pointer to a two-dimensional array. In C, you can't just specify a pointer value and assign to it; you must use the * operator to dereference the array, and assign through that.
Here is a short code sample that shows how to dereference a pointer, and then repeats your error.
main()
{
int a[10];
*(a + 1) = 0; // proper use of * to dereference
a + 1 = 0; // will not compile; error is "l-value required"
}
But in C, there is a shortcut way to add to a pointer and then dereference it. It is the use of square brackets and an index value:
a[1] = 0; // index the array
In C, the expressions *(a + i) and a[i] mean exactly the same thing, by definition.
http://en.wikipedia.org/wiki/C_syntax#Accessing_elements
It looks like you are trying to create a random matrix, one row at a time. And you are allocating memory for each row. Your basic matrix declaration should be an array of pointers to rows.
int *matrix[rows];
for (i = 0; i < rows; ++i)
{
// either of these lines will work; pick just one
*(matrix + i) = AllocateRandomRow(cols); // explicit add-and-dereference
matrix[i] = AllocateRandomRow(cols); // simpler: just index array
}
I favor the second, simpler syntax for solving this problem. You are indexing an array; just use the square brackets.
Here is a free online text that describes how to dynamically allocate a matrix.
http://www.eskimo.com/~scs/cclass/int/sx9b.html
Here's an example of simpler case to understand this more complex case:
int b = 4;
int *a = &b; // Allowed and works because a is a pointer to an integer
a+1 = 5; // Not allowed no idea about the type of a+1 and it could be used!!
Why this relates to your problem ?
int(*matrix)[5][5];
printf("%p\n",matrix);
printf("%p\n",matrix+1);
Output
0xb7753000
0xb7753064
Difference between the above pointers is of 6*16 + 4 = 100. This number is nothing but row*col*sizeOf(int) = 5*5*4 = 100
Therefore, what you want to do was accessing the cells in matrix, however what you are actually doing is trying to access a memory that your not allowed to use as in the first simple example.
Example of what you are actually doing vs what you wanted the program to do:
int(*matrix)[5][5];
matrix + 0 => address of matrix
matrix + 1 => address of matrix + 100 bytes (you expected + 4 bytes instead)
matrix + 2 => address of matrix + 200 bytes (you expected + 8 bytes instead)
etc...