Related
This question already has answers here:
Why is char[][] = {{...}, {...}} not possible if explicitly given a multidimensional array?
(5 answers)
Array type has incomplete element type error in C [duplicate]
(1 answer)
Closed 1 year ago.
Why do we need the column size for
int arr[][] = { {1,2,3},{1,3,5} };//int arr[][3]
In this particular example, why can't the compiler deduce it from the data that it has to pack only 3 elements each into each row? Why is there a limitation on compiler for doing it?
I can understand if it was
int arr[][] = { 1,2,3,1,3,5 };
then the compiler has no information of how much data has to be packed into each row.
I read a similar question Why do we need to specify the column size when passing a 2D array as a parameter?. But it doesn't contain the answer.
Edit: To avoid confusion, I am talking about the exact format of data mentioned above.
What does prevent a compiler from deducing the size of column?
The C standard.
From the standard:
6.7.9 Initialization
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
So you can initialize "an array of unknown size" but you can't initialize "an array of unknown size of array of unknown size".
Because you may want the array size to be greater than it is deduced. Like
int arr[5] = {1, 2, 3}; // Last two elements are zero.
If you declare the array like
int arr[][] = { {1, 2, 3}, {1, 3, 5, 7} };
What should the compiler do, report the error, since it expects the array int array[][3], or make the array int array[][4]? This decision is left to be up to a human.
The 2-D arrays are flat in the memory. For example int arr[3][3] and int arr[9] have the same storage. Thus, it is allowed to initialize both vectors by one initializing lists, it can be considered as placing initializing list values directly to a flat memory:
#include <stdio.h>
#include <memory.h>
int main(void) {
int arr2d[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int arr1d[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
printf("size: %d\n", sizeof(arr2d) == sizeof(arr1d));
printf("memcmp: %d\n", memcmp(arr2d, arr1d, sizeof(arr2d)));
return 0;
}
// size: 1
// memcmp: 0
Extending the above, all 4 functions bellow declare and initialize the same array int arr[3][3] differently:
#include <stdio.h>
void arr2_list2(void) {
int arr[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
printf("int arr[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}:\n");
for (int i = 0; i < 3; ++i)
printf("%d %d %d\n", arr[i][0], arr[i][1], arr[i][2]);
return 0;
}
void arr2_list1(void) {
int arr[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
printf("int arr[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}:\n");
for (int i = 0; i < 3; ++i)
printf("%d %d %d\n", arr[i][0], arr[i][1], arr[i][2]);
return 0;
}
void arr2open_list2(void) {
int arr[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
printf("int arr[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}:\n");
for (int i = 0; i < 3; ++i)
printf("%d %d %d\n", arr[i][0], arr[i][1], arr[i][2]);
return 0;
}
void arr2open_list1(void) {
int arr[][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
printf("int arr[][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}:\n");
for (int i = 0; i < 3; ++i)
printf("%d %d %d\n", arr[i][0], arr[i][1], arr[i][2]);
return 0;
}
int main(void) {
arr2_list2();
arr2_list1();
arr2open_list2();
arr2open_list1();
return 0;
}
// int arr[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}:
// 0 1 2
// 3 4 5
// 6 7 8
// int arr[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}:
// 0 1 2
// 3 4 5
// 6 7 8
// int arr[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}:
// 0 1 2
// 3 4 5
// 6 7 8
// int arr[][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}:
// 0 1 2
// 3 4 5
// 6 7 8
Imaging int arr[][] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}; is allowed, why would not int arr[][] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; be allowed then, but how can the compiler decide what a human means in the statement
int arr[][] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
int arr[1][9], or int arr[3][3], or int arr[9][1]?
Simple answer - in a declaration like
int arr[][] = { ... };
the element type is int [], which is an incomplete type, and you cannot declare an array where the element type is incomplete. The presence or absence of an initializer doesn’t change that. All an initializer can tell you is how many elements you have of the given element type; it can’t tell you what that element type is.
By contrast, in the declaration
int arr[] = { ... };
the element type is int, which is a complete type. You still need something in the initializer to determine the number of elements, but it’s not telling you how big each element needs to be.
That's because although the [][] syntax looks like array-of-arrays, in memory it is laid like 1-D array. If we imagine a 3x3 chessboard it would be laid out as {1A, 2A, 3A, 1B, 2B, 3B, 1C, 2C, 3C}. The only way to access it as 2-D is to address it as [row + column * columnsize].
Now it's clear that you MUST know the columnsize in order to even start thinking about accessing the elements of the array. Where is this columnsize parameter stored? The array is of type int (*)[3]. Columnsize is an integral part of the type as much as "t" is a part of int.
What are you asking for is auto type. The compiler would have to determine the entire type on its own. It's equivalent of wanting auto arr = 1; or auto arr = "foo";. C compiler doesn't deal in such tricks.
Notice that columnsize is entirely different creature than the length of an array. int arr[] = {1} is of exactly same type as int arr[] = {1,2,3} The compiler couldn't care less about the length (actual size in memory) of the array, not going out of bounds is entirely your responsibility. That's why one element could be left unspecified. Not because the compiler can figure it out, but because the compiler ignores it.
int arr[][2] = {1,2,3,4,5,6} is of entirely different type than int arr[][3] = {1,2,3,4,5,6}, even though they're same size in memory. To the compiler, they're like int[1] and char[4].
The {{},{}} is just a syntactic sugar to help YOU, not the compiler.
hopping you and your family are doing great concedering the situation.
I'm working on a program to multiply a matrix and a vector, using multithreading (MPI) in C. Here it is :
#include <mpi.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int rank, size;
int mat[2][3] = {{1, 2, 3}, {4, 5, 6}};
int vector[3] = {7, 8, 9};
int vecRes[3] = {50, 122};
int nbLigMat = sizeof(mat) / sizeof(mat[0]);
int nbColMat = sizeof(mat[0]) / sizeof(int);
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int sendbuf[sizeof(vector) / sizeof(mat[0])], recvbuf, recvcounts[size];
if (size == nbColMat)
{
for (int i = 0; i < nbLigMat; i++)
sendbuf[i] = mat[i][rank] * vector[rank];
for (int i = 0; i < size; i++)
recvcounts[i] = 1;
MPI_Reduce_scatter(sendbuf, &recvbuf, recvcounts, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
if (rank < nbLigMat)
printf("Processeur num %d / outputVector[%d] : %d\n", rank, rank, recvbuf);
}
else
{
if (rank == 0)
{
printf("Le nombre de processeurs necessaires est : %d\n", nbColMat);
}
}
MPI_Finalize();
return 0;
}
It does work for the following matrix/vector couples :
{{1, 2}, {3, 4}} and {5, 6}; {{1, 2, 3}, {4, 5, 6}} and {7, 8, 9}; {{1, 2, 3, 4}, {5, 6, 7, 8}} and {9, 10, 11, 12} but for example with {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} and {10, 11, 12}, the result should be {68, 167, 266} but my output vector is {68, 167, 476}.
I realised that, I don't know for which reason, the elements in my input vector are changed between the beginning and the first for loop for each process even though i don't interact with it :
In process 0, my input vector became a {40, 11, 12} in the first loop and a {40, 280, 12} at the end. In process 1, {55, 11, 12} and then {55, 88, 12}. In p2, {72, 11, 12} and then {72, 108, 12}. These numbers match the result numbers of the mat[i][rank]*vector[rank] calculation in the first loop, but I don't understand how they get in my input vector.
Maybe i understood something wrong on how MPI works but i don't manage to find out how those number get there and overwrite my input vector. Hopping the explanation is clear enough..
I think the error is in the dimension of sendbuf. If I run your example with {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} and {10, 11, 12} then:
sizeof(vector) / sizeof(mat[0]) = 1
which is too small, e.g. in your loop you assign values to sendbuf from i = 0 to i = nbLigMat-1.
If I replace the definition of sendbuf to be:
int sendbuf[nbLigMat], recvbuf, recvcounts[size];
then I get the correct answer:
Processeur num 0 / outputVector[0] : 68
Processeur num 1 / outputVector[1] : 167
Processeur num 2 / outputVector[2] : 266
I'm working on an Arduino project which requires an array of arrays, each with varying sizes. Here are the arrays:
int seg0[6] = {10, 3, 4, 5, 12, 11};
int seg1[2] = {3, 4};
int seg2[5] = {10, 11, 2, 4, 5};
int seg3[5] = {10, 11, 2, 12, 5};
int seg4[4] = {3, 11, 2, 12};
int seg5[5] = {10, 3, 2, 12, 5};
int seg6[6] = {10, 3, 2, 4, 5, 12};
int seg7[3] = {10, 11, 12};
int seg8[7] = {10, 11, 12, 5, 4, 3, 2};
int seg9[6] = {10, 3, 11, 2, 12, 5};
I'd like to have them all in one big array, so that I can enter a number, eg. 8, and then it would give me the array with the index number which was specified (array[0] would give seg0, array[8] would give seg8, etc).
Anyone have any tips?
Thanks
I guess you are asking about dimension array
int seg0[6] = {10, 3, 4, 5, 12, 11};
int seg1[2] = {3, 4};
int seg2[5] = {10, 11, 2, 4, 5};
int seg3[5] = {10, 11, 2, 12, 5};
int seg4[4] = {3, 11, 2, 12};
int seg5[5] = {10, 3, 2, 12, 5};
int seg6[6] = {10, 3, 2, 4, 5, 12};
int seg7[3] = {10, 11, 12};
int seg8[7] = {10, 11, 12, 5, 4, 3, 2};
int seg9[6] = {10, 3, 11, 2, 12, 5};
// Keep all of seg in a dimension array
int* dimention_array[10] = {seg0, seg1, seg2, seg3, seg4, seg5, seg6, seg7, seg8, seg9};
// Print first element of |seg0|
printf("%d", dimention_array[0][0]);
I am confused on how these C pointers work.
Here is what I am trying to do:
Create a struct that has a row, column, and grid (2d array of predefined size).
typedef struct
{
int row;
int column;
int (*matrix)[GRID_SIZE];
} parameters;
Now I create one
int grid[GRID_SIZE][GRID_SIZE] = {
{6, 5, 3, 1, 2, 8, 7, 9, 4},
{1, 7, 4, 3, 5, 9, 6, 8, 2},
{9, 2, 8, 4, 6, 7, 5, 3, 1},
{2, 8, 6, 5, 1, 4, 3, 7, 9},
{3, 9, 1, 7, 8, 2, 4, 5, 6},
{5, 4, 7, 6, 9, 3, 2, 1, 8},
{8, 6, 5, 2, 3, 1, 9, 4, 7},
{4, 1, 2, 9, 7, 5, 8, 6, 3},
{7, 3, 9, 8, 4, 6, 1, 2, 5}};
parameters *data = (parameters *) malloc(sizeof(parameters));
data->row = 1;
data->column = 2;
data->matrix = grid; // is this right?
int** test = data->matrix; //this is wrong.
My goal is to pass in that struct as data when creating a new thread. I am really clueless on how the pointer system works when creating the 2D array in the struct and then using it later. Any help is appreciated.
Edit... here is my new code.. looks like its working! :)
parameters *data = malloc(sizeof(parameters)); //make sure to free thread after
data->row = 1;
data->column = 2;
data->matrix = grid;
int (*test)[GRID_SIZE] = data->matrix;
printf("first value, %d\n", test[0][0]);
Something like this should work.
Define your struct like this:
typedef struct
{
int row;
int column;
int matrix[GRID_SIZE][GRID_SIZE];
} parameters;
Copy the matrix like this:
memcpy( data->matrix, grid, sizeof(grid) );
I'm supposed to make a method to test if two arrays have the same values in reverse order.
public static boolean areReversed (int [] t , int [] q)
{
boolean identical = false;
if(t.length != q.length){ identical = false;}
else{
for(int x = (t.length -1) , y = 0; -1 < x; x-- , y++)
{
if(t[y] == q[x])
{
identical = true;
}
}
}
return identical;
}
I test it by running it through these if statements with the following pre-determined arrays
int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
int[] b = {0, 9, 8, 7, 6, 5, 4, 3, 2, 1};
int[] c = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int[] d = {9, 8, 7, 6, 5, 4, 3, 2, 1};
int[] e = {1, 2, 3, 4, 5, 4, 3, 2, 1};
int[] f = {1, 2, 3, 4, 4, 3, 2, 1};
int[] g = {1, 3, 5, 7, 9, 0, 2, 4, 6, 8};
int[] h = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
int[] i = {1, 1, 3, 3, 5, 5, 7, 7, 9, 9};
//test for areReversed, uncomment the next two lines to test your method
if(areReversed(a, b) && !areReversed(a, g) && !areReversed(a, c)) System.out.println("Basic areReversed method test PASSED");
else System.out.println("Basic areReversed method test FAILED");
My method doesn't pass the test, am I making an oversight somewhere in my code?
Yes, you are indexing to two arrays in the same order. You are essentially checking that they are equal, not that they are the reverse of each other.
Also, remember that a function can return at any point Think about this and think about how you could make your function more efficient in a case where the arrays look like this:
[1,2,3] and [4,2,4].
How many comparisons do you actually need to make before you can tell us the arrays are not the same.
This is what you should do:
public static boolean areReversed (int [] t , int [] q)
{
if(t.length != q.length) return false;
for(int x = (t.length -1) , y = 0; -1 < x; x-- , y++)
{
if(t[y] != q[x]) return false;
}
return true;
}
Note that I'm returning false from the method as and when it is known that the reversed arrays are unequal. Hence, at the end, if false isn't returned yet, the arrays have to be reversed equal, and thus, true is returned.