I'm trying to print a dynamic 2D array in C, the problem is that with the code it prints fine the first time but if its printed anymore times its missing the bottom row.
This is the code I'm working with:
void display_board( int height, int width, char** gameBoard ) {
int i;
char *rowString;
rowString = malloc(((width*2)+1) * sizeof( char ));
for( i = 0; i < ((height*2) + 1); i++ ){
rowString = *(gameBoard + i);
printf("%s\n",rowString);
}
free(rowString);
}
The game being made is dots and boxes so width and height are the amount of boxes, the arrays are actually allocated as height*2+1 and width*2+1 and is set up to look like this if the height is 2 and width is4, note that the example has all the edges filled in already but normally the edges would just be white spaces:
x-x-x-x-x
| | | | |
x-x-x-x-x
| | | | |
x-x-x-x-x
When I print this the first time it looks like that, but if I try and print it again it looks like this:
x-x-x-x-x
| | | | |
x-x-x-x-x
| | | | |
Any idea on why this is happening?
Before the loop you allocate memory and assign it to the pointer variable rowString. But inside the loop you reassign the variable to point to somewhere else, loosing the original pointer to your allocated memory. Later when you try to free the memory you free the memory in the "2d matrix" instead of the memory you just allocated.
All of this leads to undefined behavior as you then later try to dereference the previously free'd memory (*(gameBoard + i)).
The obvious solution here is to not reassign the pointer, but to copy the string, e.g. with strcpy. Another pretty obvious solution would be to not allocate memory at all, and not even use the rowString variable, as you don't really need it but can use the pointer *(gameBoard + i) directly in your printf call.
Related
If we create a char array:
char strings[3][10] = {"Apple","Banana","Grape"};
and a pointer of type char:
char *pstrings[] = {"Apple","Banana","Grape"};
If we print the addresses of the elements, the char array elements will be 10 bytes apart and the elements of the pointer don't seem to follow one another.
How does your program know where to find the next element of the char pointer if the elements do not follow each other in memory?
Well you are initializing the array of char* with that information.
In fact char*[] contains individual char* pointing to the respective string literal. How does it come? Well "abc" is basically a null terminated char array that decays into pointer to first element of the array which is 'a' and now if that is known it isn't hard to access them. The addresses are being stored basically. In the second case you are initializing the char* array wit those value. Those string literals need not be from contiguous memory.
+-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+
ADDRESS |Random | |Random | |Random |
+-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+
|A|p|p|l|e| |B|a|n|a|n|a| |G|r|a|p|e|
+-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+
\ | /
\ | /
\ | /
+-+-+-+-+-+-+-+-+-+
| 0 | 1 | 2 |
+-+-+-+-+-+-+-+-+-+
That's why you got different values when you printed strings[0], strings[1] etc.
Program just uses the initialized values that is stored in pstrings and that contains the address of those string literals. That's how we use it.
In the first case, same content as your string literals - we are initializing them in the char array which are in turn contiguous.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
ADDRESS |strings + 0 |strings + 10 |strings + 20 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
|A|p|p|l|e| | | | | |B|a|n|a|n|a| | | | |G|r|a|p|e| | | | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| 0 | 1 | 2 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
As a result we can have those modifiable strings each being stored in an array of 10 chars. char p[]="abc"; is equivalent to char p[]={'a','b','c','\0'} same happens here.
Also know one thing, the second case also the pointer values are stored in contiguous memory.
These wonderful ascii-art explanation is provided by Keine Lust.
I wrote this code that check suduko answers and for some reason my the array which I sum the squares of the suduko into is all zeros in the functions I zero it in, but when I use it in my check function it isn't all zeros
if i move the exact same code of my array zeroing function to my other function and run it it works.
(i am using c99, dont know if it matters)
Any ideas?
int squareSum[5][5];
//set array elements to zero
setArrayToZero(squareSize, squareSize, squareSum);
/*for(int i = 0; i<squareSize; i++){
for(int j = 0; j<squareSize; j++)
squareSum[i][j] = 0;
}*/
printf("%d, %d\n%d, %d\n\n", squareSum[0][0], squareSum[0][1], squareSum[1][0], squareSum[1][1]);
this is the array is case squareSize is two
if i add the for in the comments in, the array isall zeros, and as you can see below its the exact same as the function i call.
void setArrayToZero(int rows, int columns, int array[][columns]){
for(int i = 0; i<rows; i++)
for(int j = 0; j<columns; j++)
array[i][j] = 0;\\if i print the array in function its all zeros.
p.s
i know i am using only part of the array, its an assignment from the university and we are not allowed to use malloc so i am creating the array at thier max size - 25.
thank you in advance.
full c file:
https://drive.google.com/open?id=1L00L3lvMYNcaz2SswEBnmi9KO-79oaHg
all the print functions, are part of the demand for the course (for auto checking)
A reference to an object of type array-of-T which appears in an
expression decays (with three exceptions) into a pointer to its first
element; the type of the resultant pointer is pointer-to-T.
So that means in this case also (this is not one of those 3 exceptions) your passed array will decay into pointers and now you change to the array by accessing the address, that's why it will be retained in the callee function.
You are doing it the right way. The problem is not with passing or anything. Maybe you are accessing it wrong or maybe you didn't initialize it properly. But there is nothing wrong with the zeroing out.
And for further information everything is pass by value in C. There is nothing called pass by reference in C. The pointer workings makes us think that there is something called pass by reference in C but that's not the case, here also pointer variables are copied into some local variable in the called function. but as we have those addresses in the called function and we access them and make changes - they retain in callee function.
After OP posted the sample code
Apaprt from the overly complicated sudoku checking logic there is much more going wrong.
I will just mention the printing part.
In C elements of 2d-arrays are stored sequentially. When we pass the 2d array to the function we need to specify the column size so that we can determine the correct element.
Suppose you want to access a[4][7] in 10x13 array. The element would be at the address &a[0][0]+4*13+7. That's why the column part is passed as an argument.
Now what you did :
int squareSum[5][5], rowColSum[25][2];
//set arrays elements to zero
setArrayToZero(size, 2, rowColSum);
setArrayToZero(squareSize, squareSize, squareSum);
The first one is alright. As there are 2 columns. But what about the second one?
here you are telling the function that you are passing an array with column size = 2 but that is not the case. It is still the 2d array with 5 columns.
That's where you had the problem. Suppose you initialize the array with 10,21,34,14
Suppose grid is 5x5 array (in your case it's 25x25)
grid[5][5] array
And you do this
for(int i = 0; i<squareSize; i++)
for(int j = 0; j<squareSize; j++)
scanf("%d",&grid[i][j]);
/*
Input is 13 17 19 23
*/
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
/ \ \ / \ \
13 17 19 23
Now you access it like this
You pass it to the function with this call print2dArray(int row, int col, int g[][col])
You call like this `print2dArray(2,2,grid);``
...
for(int i = 0; i<row; i++)
for(int j = 0; j<col; j++)
printf("%d",&grid[i][j]);
Now you will print these elements (i) : denotes the order
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
+-----+-----+-----+------+-----+-----+-----+----+----+----+--...\
/ \ \ ^ ^ / \ \
13 17 | | 19 23
(1) (2) (3) (4)
Similarly, those were uninitialized in your case. That's why you got those weird results. You were initializing some elements of the 2d array to 0 but when you are reading the array then you were accessing some different elements. That's why the wrong result.
Solution for this:
Call int correctSum = inputGrid(squareSize, 25, grid); Note that it should be squareSize. Accordingly change the storage of digitsCounter in inputGrid.
The function signature for inputGrid would be inputGrid(size, col, grid[][col]);
Same when calling the
setArrayToZero(size, 2, rowColSum); and
setArrayToZero(squareSize, 5, squareSum);
I simply didn't check the logic. The answer deals with explaining the printing behavior of the 2d array.
The Motivation
I'm attempting to save various environments via setjmp for the purpose of jumping back to them later and calling functions and making sure that the stack frames run into each other. For Example:
env[0] stack:
----------
| text |
----------
| data |
----------
| |
| |
| |
| |
| |
| |
| |
| ~~~~ |
----------
where the tildes represent the stack frames of main etc.
env[1] stack:
----------
| text |
----------
| data |
----------
| |
| |
| |
| **** |
| **** |
| **** |
| **** |
| ~~~~ |
----------
Where the stars represent a large array I've allocated.
The idea is that if I longjmp to env[0] and start running some methods, then longjmp to env[1] and start running some methods, the stack frames of env[0] will start to fill up the empty space in that array, and the stack frames of env[1] will be on top of that array, and not overwrite the stack frames of env[0]. Basic threading.
I'd also like to have more than just two threads, in fact, I'd like MAXTHREADS. Intuitively it works like this:
for(int i = 0; i < MAXTHREADS; i++) {
char c[STACKSIZE];
if( setjmp(env[i]) != 0 ) {
/* Stuff that thread i will do goes here */
}
}
Test 1
However, as you can clearly see in the following test program, each c array started at the same spot on the stack, defeating the purpose.
for(int i = 0; i < 10; i++) {
char c[10];
printf("On Iteration %d array starts at %x and goes to %x\n",i,c,c+10);
}
Outputs:
On Iteration 0 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 1 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 2 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 3 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 4 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 5 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 6 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 7 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 8 array starts at ffbfef02 and goes to ffbfef0c
On Iteration 9 array starts at ffbfef02 and goes to ffbfef0c
This makes sense for a multitude of reasons, scope dictates that the c array ceases to exist at the end of the loop, additionally the compiler probably moves it outside of the loop because the size is static.
Test 1 gave me the size I want, but not the allocation I want
Test 2
So my next thought was to allocate an array of STACKSIZE * i, so that even though the arrays each started at the same spot, they would be bigger each time and push up my stack pointer far enough when the time came to switch to that environment. Here's the test:
for(int i = 0; i < 10; i++) {
char c[10 * i];
printf("On Iteration %d array starts at %u and goes to %u\n",i,c,c+(10*i));
//note: switched from %x to %u to make comparison mentally simpler
}
However, this outputs
On Iteration 0 array starts at 4290768760 and goes to 4290768760
On Iteration 1 array starts at 4290768744 and goes to 4290768754
On Iteration 2 array starts at 4290768720 and goes to 4290768740
On Iteration 3 array starts at 4290768688 and goes to 4290768718
On Iteration 4 array starts at 4290768648 and goes to 4290768688
On Iteration 5 array starts at 4290768592 and goes to 4290768642
On Iteration 6 array starts at 4290768528 and goes to 4290768588
On Iteration 7 array starts at 4290768456 and goes to 4290768526
On Iteration 8 array starts at 4290768376 and goes to 4290768456
On Iteration 9 array starts at 4290768280 and goes to 4290768370
It's a little hard to see at first, but due to the large numbers, you can focus on only the last three digits.
The first array goes from 760 to 760 -- fine, it's for i = 0
The second array goes from 744 to 754 -- fine, we moved a bit, but it's an array of size 10 in the general position that we want it in
The third array goes from 720 to 740 -- uh-oh, the array didn't start in the same spot as the others, and it's double the size.
To Illustrate the pattern on the stack, each * represents 10 chars in an array, and gaps between chunks of stars are the gaps between the arrays:
*
*
*
*
*
*
~
The tilde is the main,etc as before.
The pattern goes on. This is likely machine dependent, but my machine is allocating the arrays in order, rather than going back down the bottom each time as it did with constant size arrays.
Test 2 gave me the allocation I want, but sizes WAY larger than I'd like.
Test 3
Now having learned that my machine will allocate arrays overwriting each other if they're the same size, but stacked on top of each other if they vary in size, I thought that maybe I could allocate STACKSIZE + i instead of STACKSIZE * i of each. I ran this experiment:
for(int i = 0; i < 10; i++) {
char c[10+i];
printf("On Iteration %d array starts at %u and goes to %u\n",i,c,c+10+i);
}
Which outputs:
On Iteration 0 array starts at 4290768808 and goes to 4290768818
On Iteration 1 array starts at 4290768792 and goes to 4290768803
On Iteration 2 array starts at 4290768776 and goes to 4290768788
On Iteration 3 array starts at 4290768760 and goes to 4290768773
On Iteration 4 array starts at 4290768744 and goes to 4290768758
On Iteration 5 array starts at 4290768728 and goes to 4290768743
On Iteration 6 array starts at 4290768712 and goes to 4290768728
On Iteration 7 array starts at 4290768688 and goes to 4290768705
On Iteration 8 array starts at 4290768664 and goes to 4290768682
On Iteration 9 array starts at 4290768640 and goes to 4290768659
After analysis, it's using the same allocation behavior I expected.
Test 3 gave me the allocation I want, and sizes close to what I want, but still not perfect
The Question
So Test 3's strategy could work in my original code up top, allocate MAXTHREADS arrays of STACKSIZE + i, saving the env between each, but it seems suboptimal. I'm allocating extra space in each array simply to trick my compiler.
Is there a better way to do this? Some other trick to make the compiler allocate fresh arrays of STACKSIZE each time?
How do I get the allocation of tests 2 and 3, with the size of test 1?
You have to do something like this:
jmp_buf states[NUMTHREADS]
char stacks[NUMTHREADS][STACKSIZE];
// your scheduler starts *after* this!
for(;;) {
// setjmp to remember the current thread's state
// longjmp to thread i+1 and use stacks[i+1][top]
}
|--------|
// / |4 4 4 |
// |--------| 4 |
// / |3 3 3 | 4 |
// |---------|3 | |
// / | 2 2 2 |3 | /
// |---------|2 |__|
// | 1 1 1 |2 | /
// | 1 1 1 |__|
// | 1 1 1 | /
// |_________|
double arr[4][3][3] = {{1,1,1,1,1,1,1,1,1},{2,2,2,2,2,2,2,2,2},{3,3,3,3,3,3,3,3,3},{4,4,4,4,4,4,4,4,4}};
I consider that this array consists of 4 layers.
I want to create pointer to layer of array and traverse through layers of that array using pointer.
I try :
double (*pp1)[sizeof(arr[0]) / sizeof(ar[0][0][0])];
pp1 = arr[0];
and get error from intelIsense:
value of type (double (*)(3) can`t be assigned to double(*)(9)
So if you do:
int i;
double arr[4][3][3] = {{1,1,1,1,1,1,1,1,1},{2,2,2,2,2,2,2,2,2},
{3,3,3,3,3,3,3,3,3},{4,4,4,4,4,4,4,4,4}};
double (*pp3)[3][3];
pp3 = arr;
for (i = 0; i <= 3; i++)
{ printf("pp3 + %d is %f \n", i, ***(pp3 + i));
}
Then you get the desired behavior. The problem with your code is that, just as the compiler is telling you, you are trying to assign a pointer to an array of 9 double (double (*pp1)[sizeof(arr[0] / sizeof(arr[0][0][0])] evaluates to double (*pp1)[9] ), but you need a pointer to an array of 3 of array of 3, which is what you declared with double arr[4][3][3]. From my tests, gcc will accept the double (*pp1)[9] with a compiler warning, which is what I tried to get at in my comment below. Hope that clears things up.
If you want to keep this general, then what you really want is double (*pp3)[sizeof(arr[0]) / sizeof(arr[0][0])][sizeof(arr[0][0]) / sizeof(arr[0][0][0])], which is a bloody nightmare.
EDIT: Forgot a dereference... Should've copy/pasted haha. Also added explanation about the question's code behavior. Fixed as per comments.
Why not simply get the direction of the first element of a given layer?
double *pp1 = &ar[0][0][0];
double *pp2 = &ar[1][0][0];
/* and so on */
While trying to figure out this issue i got some results.
I find out that the following statements raises no errors from compiler
double arr[4][4][9];
double (*pp3)[9];
pp3 = arr[0];
So, is it right to deduce from code above that pointer can be assigned to array only in case if number of elements to which it points is equall to the smallest dimension of array?
update:
I think that pointer can be created on the smallest layer of array only.
Can somebody explain this?
I need a multidimensional array of chars that is dynamic in only one dimension...
I have to store a pair of strings with a length of 10 (or less) chars each, but with a variable number of "pairs".
My idea was this
char (*instrucao)[2][10];
Which gives me a pointer to a 2x10 array of chars, but this is not working properly when i do something like this:
char strInstrucoes[117], *conjunto = calloc(21, sizeof(char));
instrucao = calloc(1, sizeof(char[2][10]));
conjunto = strtok(strInstrucoes,"() ");
for(i = 0; conjunto != NULL; i++){
realloc(instrucao, i+1*sizeof(char[2][10]));
sscanf(conjunto,"%[^,],%s", instrucao[i][0], instrucao[i][1]);
printf("%s | %s\n", instrucao[i][0], instrucao[i][1]);
conjunto = strtok(NULL, "() ");
}
Having strInstrucoes as (abc,123) (def,456) (ghi,789), I don't matrix with 3 lines of 2 pairs each like this:
abc | 123
def | 456
ghi | 789
but instead this is what I'm getting:
abc | 123
def | 45def | 45de
ghi | 789
What's the right way to do this?
Thanks!
You should assign the pointer the new address realloc returns
instrucao = realloc(instrucao, (i+1)*sizeof(char[2][10]));
Note that for error checking, you may desire to assign to a new pointer and check for NULL. Also note the parens - you basically just added i instead of multiplying with the required size. Easily overseen.
Note that there is no need for the initial calloc. Just initialize instrucao to NULL, and realloc will behave like malloc when first passed a null pointer.
You would do much better to find a library with a container that will meet your needs. At the very worst, using none of the much better libraries, you could have two separate arrays, each of them holding half of the pair.