C Programming - Integer value within struct becomes "random" after assignment [duplicate] - c

This question already has an answer here:
How do I get a function to modify any of the parameters?
(1 answer)
Closed 4 years ago.
I've searched for a fix to this issue but haven't been able to find an explanation. I have a two dimensional struct which has an integer variable within it.
typedef struct
{
int example;
} Example;
typedef struct
{
Example two_dimensional_array[5][5];
} Example_Outer;
I then set this variable to 0 for all fields using the following function and print the current values.
void initialise(Example_Outer example)
{
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
example.two_dimensional_array[i][j].example = 0;
}
}
print_example(example);
}
During this print, the values all appear as 0's like they should.
Output:
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
I then run a new function that utilises the exact same print code, and receive the following output:
0, 0, 0, 0, 9,
0, -394918304, 32551, -2138948520, 32764,
1, 0, 1, 0, 1775692253,
21904, -394860128, 32551, 0, 0,
1775692176, 21904, 1775691312, 21904, -2138948320,
print method:
void print_example(Example_Outer example)
{
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
printf("%d, ", example.two_dimensional_array[i][j].example);
}
printf("\n");
}
}
main method:
int main( int argc, const char* argv[] )
{
Example_Outer example;
initialise(example);
printf("---------------\n");
print_example(example);
}
Why do the variables not remain set to 0? What is causing this and how can I fix it? Thank you!

First, you can initialize your struct like bellow in a simple way :
Example_Outer example = { 0 };
Or in second way :
typedef struct
{
Example two_dimensional_array[5][5] = { 0 };
} Example_Outer;
Now in your code , you forgot about * in your void initialise(Example_Outer example) function, and in this case you just passing a copy of struct in function.
So you should use of struct's address as parameter to the function with pointer (*) :
void initialise(Example_Outer *example)
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
example->two_dimensional_array[i][j].example = 0;
}
}
print_example(*example);
}
Finally you can pass your struct's address as following : ( Test it online ) :
int main(int argc, const char* argv[])
{
Example_Outer example;
initialise(&example);
printf("---------------\n");
print_example(example);
}

Related

Initialize 2D array in C using array of pointers

I have a static array that I want to use to initialize a dynamic array using pointers.
Right now I have this:
boardinit[BOARD_HEIGHT][BOARD_LENGTH] = {
{-4, -2, -3, -5, -6, -3, -2, -4},
{-1, -1, -1, -1, -1, -1, -1, -1},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1},
{4, 2, 3, 5, 6, 3, 2, 4},
};
int main()
{
int board[BOARD_HEIGHT][BOARD_LENGTH];
initboard(board);
for (int j = 0; j < BOARD_HEIGHT; j++)
{
for (int i = 0; i < BOARD_LENGTH; i++)
printf("%d ", board[j][i]);
printf("\n");
}
return 0;
}
void initboard(int (*pboard)[BOARD_HEIGHT])
{
for(int i = 0;i<BOARD_HEIGHT;i++)
pboard[i] = boardinit + i;
}
I want board[BOARD_HEIGHT][BOARD_LENGTH] to initialize as boardinit[BOARD_HEIGHT][BOARD_LENGTH] by passing board to initboard() using pointers, but can't seem to get it to go.
To copy the contents boardinit to the value of board, just use this:
memcpy(board, boardinit, sizeof(board));
If that does not work, try this:
void initboard(int pboard[BOARD_HEIGHT][BOARD_LENGTH]) {
for (int i = 0; i < BOARD_HEIGHT; i++)
for (int j = 0; j < BOARD_LENGTH; j++)
pboard[i][j] = boardinit[i][j];
}
"I have a static array that i want to use to initialize a dynamic array using pointers."
The problem with arrays of pointers is that each call to [m][c]alloc() is not guaranteed (in fact is not likely) to provide a single contiguous block of memory. i.e., this is a common approach that provide many little areas of memory:
int **array = malloc(sizeof(width * sizeof(int *));
{
for(int i=0; i<width; i++)
{
array[i] = malloc(height*sizeof(int));
}
}
Thus, the initializer would need to be broken into several memory block locations.
A simpler and more efficient way to do this is with a single dynamic memory allocation call, guaranteeing a single contiguous block of memory, then a single memcpy() is possible using the initializer into the pointer location returned from [m][c]alloc(). The only problem then is how to access the memory area with array notation. The example below illustrates how this can be done using *(ptr + index) notation...
//assuming your other code above
int main(void)
{
int elements = BOARD_HEIGHT*BOARD_LENGTH;
int *pArray = calloc(elements, sizeof(int));
if(pArray)
{
memcpy(pArray, boardinit, sizeof boardinit);
for(int i=0; i<BOARD_HEIGHT;i++)
for(int j = 0;j<BOARD_LENGTH;j++)
printf("%d\n", *(pArray + (i + j)));
free(pArray);
}
return 0;
}

How to fix ' Error: invalid read of size 4'

I'm trying to learn C and am completing different challenges in order to learn faster. The code seems logical to me and should progress. However, I'm getting an invalid read of size four on line 29
I've tried to change the data type that gets parsed through, but it didn't seem to work.
#include <unistd.h>
typedef struct s_grid
{
int x;
int y;
} t_grid;
void set_point(t_grid *coord, int i, int j)
{
coord->x = i;
coord->y = j;
}
//check loccation of next zero
int where_is_zero(int **sudoku)
{
int x;
int y;
t_grid coord;
x = 0;
y = 0;
while (x < 9)
{
y = 0;
while (y < 9)
{
if (sudoku[x][y] == 0) //Here I'm getting the error.
{
set_point(&coord, x, y);
return (0);
}
x++;
}
y++;
}
return (1);
}
int solve_sudoku(int **grid)
{
int row;
int col;
int num;
t_grid coord;
if (where_is_zero(grid) == 1)
return (1);
row = coord.x;
col = coord.y;
//where_is_zero(grid);
num = 1;
while (num <= 9)
{
if (check_number(grid, row, col, num) == 1)
{
grid[row][col] = num;
if (solve_sudoku(grid) == 1)
return (1);
grid[row][col] = 0;
}
num++;
}
return (0);
}
void ft_putchar(char c)
{
write(1, &c, 1);
}
void ft_putstr(char *str)
{
while (*str != '\0')
{
ft_putchar(*str);
str++;
}
}
//my main function
int main(int argc, char **argv)
{
int board[9][9] ={ { 0, 9, 0, 0, 0, 0, 8, 5, 3 },
{ 0, 0, 0, 8, 0, 0, 0, 0, 4 },
{ 0, 0, 8, 2, 0, 3, 0, 6, 9 },
{ 5, 7, 4, 0, 0, 2, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 0, 6, 3, 7 },
{ 9, 4, 0, 1, 0, 8, 5, 0, 0 },
{ 7, 0, 0, 0, 0, 6, 0, 0, 0 },
{ 6, 8, 2, 0, 0, 0, 0, 9, 0 } };
solve_sudoku(board);
return (0);
}
I removed some code just to highlight where the problem is. It should find the next 0 in the table and set the coordinations to my structure.
The problem lies in how you have the loop set up. See my comments below:
while (x < 9)
{
y = 0;
while (y < 9)
{
if (sudoku[x][y] == 0) //Here I'm getting the error.
{
set_point(&coord, x, y);
return (0);
}
x++; // This increments the x index while you're inside the y loop
}
y++; // This increments the y index when you meant to increment the x
}
If you swap both lines, that should work fine and will resolve your out-of-bounds error.
What would also help you write this better is instead of using a while loop, use a for loop. If you haven't covered that topic yet, it's really straightforward:
for(int x = 0; x < 9 ; ++x)
{
for (int y = 0; y < 9; ++y)
{
if (sudoku[x][y] == 0) //Here you won't get the error anymore!
{
set_point(&coord, x, y);
return (0);
}
}
}
What the for loop line means there is this: Start the loop by setting it to 0, at the end of an iteration, increment it. On the next iteration, check if x is still less than 9. If so, proceed with the next iteration.
Your problem is due to mixing types. In main() you declare:
int board[9][9] = { ....
You then pass:
solve_sudoku(board);
board has the type int (*)[9] (a pointer to array of int [9]). See C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3). Your solve_soduku expects a parameter of type int** (pointer to pointer to int).
int solve_sudoku(int **grid) { ...
The type are NOT compatible. (and your compiler should be screaming warnings at you)
board is a pointer to array of int [9], while grid is a pointer to pointer to int. You must make the types compatible. The easiest way is to change solve_sudoku to
int solve_sudoku(int (*grid)[9]) { ...
Otherwise you will need to declare board as int** and allocate and fill in main().

Implicit Decleration Of function "setWeight"

I'm writing program but getting this warning !! Can someone help me in this regard.
#include <stdio.h>
#include <stdlib.h>
typedef int bool;
#define true 1
#define false 0
#define M 5 // Define total molecules
#define MAX 31 // used to Create a range
#define N 6 // Define total nodes in the given graph
unsigned int nondet_uint(); // returns a non_deterministic uint
typedef unsigned __CPROVER_bitvector[M] bitvector;
//constrains the non_detrministic uint to be between 0 and n
unsigned int oneTon (unsigned int n){
unsigned int result = nondet_uint();
__CPROVER_assume(result>=1 && result<=n);
return result;
};
//Constrain the value between 0 and 1
unsigned int nondet (){
unsigned int num = nondet_uint();
__CPROVER_assume( num>= 0 && num <= 1);
return num;
};
//Define a structure to represent the EdgeBag that is a tuple :
// edgeBag := (i,j,edgeWeight, mask, inclusionSet, exclusionSet)
struct EdgeBag
{
int ith;
int jth;
bitvector edgeWeight;
bitvector mask;
bitvector inclusionSet;
bitvector exclusionSet;
};
// Setweight function
// Going to give the edges the weight and then allow furture calculation of inclusion and exclusion set
bitvector setWeight( bitvector node) {
bitvector edge;
edge = 00000;
for(unsigned int k=0; k<N; k++){
if ((node & (00001 << k)) == (00001 << k)) {
edge = (edge | (nondet() << k));
}
}
printf("value of the egde is %d", edge);
return edge;
}
void main(){
unsigned int pos , i, j, k, l, v, w, x, y , iVal, jVal;
unsigned int edgePos, bagNo = 0, colorNode = 0 , minColor, len = 0, cPos = 0;
bool C0 , C1 , C2 , C3;
bitvector compartment1 , compartment2 , compartment3 , compartment4, compartment5, compartment6;
bitvector nodes[N] = {compartment1, compartment2, compartment3, compartment4, compartment5, compartment6};
bitvector total , fareTotal, outTotal, inTotal;
// Represent the graph with given topology
bool graph[N][N] = {{0, 0, 1, 1, 0, 0 },
{1, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0},
{0, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0}
};
// Specify that all compartments are distinct
for(i=0; i<N; i++) {
for(j=0 ; j < N ; j++) {
if(graph[i][j] == 1) {
len = len + 1;
}
if(i != j) {
__CPROVER_assume(nodes[i] != nodes[j]);
}
}
}
// Create a structure that will contain edges.
struct EdgeBag edgeBag[len];
// Define colorGraph and colorSet for the represetaion
bool colorGraph[len][len];
unsigned int colorSet[len];
// Set the weight of the edge : for each edge in the graph call add to the esdge bag and add its edgeweight
// setWeight function and allow all possible subsets to move from a node to anotheer
// Set ith jth position and edgeweight to the position of edgeBag[len] array
edgePos = 0;
for(i=0; i<N; i++) {
for(j=0; j<N; j++) {
if (graph[i][j] == 1) {
edgeBag[edgePos].ith = i;
edgeBag[edgePos].jth = j;
**HERE IS THE PROBLEM !!!**
edgeBag[edgePos].edgeWeight = setWeight(nodes[i]);
edgePos = edgePos + 1;
}
}
}
I understand that this warning comes when compiler has not seen a declaration before function use. But i have declared the setWeight Function already and looks like type too matches. Kindly help me with this , I got stuck here since last night. Thanks
you function expects bitvector - bitvector setWeight( bitvector node)
but gets bitvector[ ] -
bitvector nodes[N] = {...};
...
[edgePos].edgeWeight = setWeight(nodes);

Changing of elements of array when passed as an index of another array

I am a rookie, and I hope this question is not a naive one!
I have the following function, where I use elements of one array as indices of another. However, despite my making no changes to the former, I see that the elements are being modified. The code is as follows:
void convert_to_bitmap(int n_shapes, int sizex, int sizey,
int ll_x[n_shapes], int ll_y[n_shapes],
int ur_x[n_shapes], int ur_y[n_shapes],
int shapes_ll_bitmap[sizex][sizey],
int shapes_ur_bitmap[sizex][sizey] )
{
int i;
for (i = 0; i < n_shapes; i++)
{
printf("%d, %d, %d, %d check1\n", ll_x[i], ll_y[i], ur_x[i], ur_y[i]);
}
for (i = 0; i < n_shapes; i++)
{
shapes_ll_bitmap[ll_x[i]][ll_y[i]] = 1;
shapes_ur_bitmap[ur_x[i]][ur_y[i]] = 1;
printf("%d, %d, %d, %d check2\n", ll_x[i], ll_y[i], ur_x[i], ur_y[i]);
}
}
And, the output shows that the first array has changed when I do so. Is there some way to keep it immutable?
Output:
0, 0, 0, 7 check1
0, 9, 0, 15 check1
1, 0, 1, 7 check1
1, 9, 1, 15 check1
2, 13, 2, 15 check1
2, 17, 2, 24 check1
2, 26, 2, 32 check1
0, 0, 0, 7 check2
0, 9, 0, 15 check2
1, 0, 1, 7 check2
1, 9, 1, 15 check2
1, 13, 2, 15 check2
2, 1, 2, 1 check2
1, 26, 2, 32 check2
This is how I invoke the function in main():
convert_to_bitmap(n_shapes, sizex, sizey, ll_x, ll_y, ur_x, ur_y, shapes_ll_bitmap, shapes_ur_bitmap);
And the declaration and initialization of the matrices in int main() is as follows:
int ll_x[n_shapes];
int ll_y[n_shapes];
int ur_x[n_shapes];
int ur_y[n_shapes];
int sizex;
int sizey;
int shapes_ll_bitmap[sizex][sizey];
int shapes_ur_bitmap[sizex][sizey];
for (i=0; i < sizex; i++)
{
for (j = 0; j < sizey; j++)
{
shapes_ll_bitmap[i][j] = 0;
shapes_ur_bitmap[i][j] = 0;
}
printf("\n");
}
Thank you!
Edit:
Here's some self-contained code:
int main(void)
{
enum { MAX_SHAPES = 100000 };
struct Rectangle rect_array[MAX_SHAPES];
int n_shapes = read_shapes_rpt("shapes.rpt", MAX_SHAPES, rect_array);
int i, j;
float pitch_x = 0.044;
float pitch_y = 0.042;
float ll_x_flt[n_shapes];
float ll_y_flt[n_shapes];
float ur_x_flt[n_shapes];
float ur_y_flt[n_shapes];
int ll_x[n_shapes];
int ll_y[n_shapes];
int ur_x[n_shapes];
int ur_y[n_shapes];
int sizex;
int sizey;
int shapes_ll_bitmap[sizex][sizey];
int shapes_ur_bitmap[sizex][sizey];
for (i=0; i < sizex; i++)
{
for (j = 0; j < sizey; j++)
{
shapes_ll_bitmap[i][j] = 0;
shapes_ur_bitmap[i][j] = 0;
}
printf("\n");
}
if (n_shapes > 0)
{
transform_to_shape_bit_locations(n_shapes, rect_array, ll_x_flt, ll_y_flt, ur_x_flt, ur_y_flt, ll_x, ll_y, ur_x, ur_y, &pitch_x, &pitch_y, &sizex, &sizey);
convert_to_bitmap(n_shapes, sizex, sizey, ll_x, ll_y, ur_x, ur_y, shapes_ll_bitmap, shapes_ur_bitmap);
printf("%d\n%d\n%d\n", n_shapes, sizex, sizey);
/* Use the shapes that were read */
}
return 0;
}
My shapes.rpt file contained the following csv values:
1.408,529.237,1.43,529.523
1.408,529.597,1.43,529.883
1.452,529.237,1.474,529.523
1.452,529.597,1.474,529.883
1.496,529.777,1.518,529.883
1.496,529.957,1.518,530.243
1.496,530.317,1.518,530.564
Your variables sizex and sizey are left uninitialized. Which means that your matrices shapes_ll_bitmap and shapes_ur_bitmap have unpredictable size (the behavior is actually undefined).
Note that when you actually assign meaningful values to your your sizex and sizey later, it is already too late. The matrices are already declared with indeterminate sizes and that's final. Once the matrices are declared, any changes to the values of sizex and sizey will have no effect on the matrices.
Your matrices end up with some indeterminate size, which results in out-of-bounds access inside convert_to_bitmap function and destruction of unrelated memory values.

unexpected result in array element with C

I am trying to insert an integer if array position is equal to 3 but unfortunately when I am printing my array a I am getting absured results like this:
0
0
2
whereas, the result expected is:
0
0
128
0
0
My code is:
#include<stdio.h>
int substitute_and_sum(int *a, int len)
{
int sum = 0, i;
for (i = 0; i < 5; i++)
{
if (i == 3)
{
a[i] = 128;
}
}
printf("%d\n", *a);
return 0;
}
int main()
{
int arr[] = { 0, 0, 2, 0, 0 };
int j = 5, i;
for (i = 0; i < 5; i++)
{
substitute_and_sum(&arr[i], j);
}
}
You have two for loops which don't play well together. Remove one or the other. For example:
int main()
{
int arr[] = { 0, 0, 2, 0, 0 };
int j = 5;
substitute_and_sum(arr, j);
for (int i = 0; i < 5; i++)
{
printf("%d\n", a[i]);
}
}
Note that I moved the printf into main. Your existing program is pretty weird.
You just need to call like following
int main(){
int arr[]={0,0,2,0,0};
int j=5,i;
//for(i=0;i<5;i++)
//{
substitute_and_sum(arr,j);
//}
}
Or use :-
void substitute_and_sum(int *a)
{
*a = 128;
}
And in main :
for (i = 0; i < 5; i++)
{
if (i == 2) //Note its index 2, not 3
substitute_and_sum(&arr[i]);
}
one for loop is enough
#include<stdio.h>
int substitute_and_sum(int* a, int len) {
int sum =0, i;
for(i=0;i< len;i++)
{
if(i==3)
{
a[i] = 128;
}
printf("%d\n" , a[i]);
}
return 0;
}
int main(){
int arr[]={0,0,2,0,0};
int j=5,i;
substitute_and_sum(&arr[i],j);
}
replace 5 with len otherwise what is the point of the argument and the last printf() is pointless because it only prints the value of the first element;
You loop over your array in both functions, just do it in one of them.
this works, whenever you send individual value of the array make it an habit of sending its index, if required for example in case like yours.
#include<stdio.h>
int substitute_and_sum(int *a, int i)
{
if (i == 3)
{
*a = 128;
}
printf("%d\n", *a);
return 0;
}
int main()
{
int arr[] = { 0, 0, 2, 0, 0 };
int i;
for (i = 0; i < 5; i++)
{
substitute_and_sum(&arr[i], i);
}
}

Resources