Integer value changes during insertion to array - c

I am having some weird problems with my code and I have no idea what I'm doing wrong. I'm relatively new to C-language, so I'd really appreciate if someone could point out if I'm doing something stupid.
I'm trying to read data from a file into two dimensional array of type state. Type state is defined as follows:
typedef uint8_t state [4][4];
I have defined method read_block that gets the file pointer as parameter and returns pointer two dimensional type state array which contains first 16 bytes from that file.
state* read_block(FILE *fp) {
state *arr = (state*) malloc(sizeof (state));
uint8_t *temp = (uint8_t*) malloc(sizeof (uint8_t)*16);
fread(temp, 16, 1, fp);
/*
for (int y = 0; y < 16; y++) {
printf("%u ", temp[y]);
}
printf("\n");
*/
int n = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
/*
printf("%u ", temp[n]);
*/
*arr[i][j] = temp[n];
n++;
}
}
return arr;
}
Code compiles and runs ok, but the type state array that method returns always contains one wrong value. Specifically, the value in position [3][0] is always wrong.
The test file I'm trying to read contains numbers:
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
I decided to check if the values are read right and if I remove comments around printf lines I get as output:
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
0 1 2 3 0 1 2 3 0 1 2 3 3 1 2 3
In which the first line is exactly correct (that is printed right after fread()), but for some reason the second line is incorrect (that is printed when inserting values into arr).
I can't figure out what is causing this. I've also tried reading values one byte at time with fread, but the same value keeps being wrong. I'm using NetBeans, so I'm not sure if this is somehow being caused by it.

You're running into operator precedence.
*arr[i][j]
is the same as
*(arr[i][j]) // or arr[i][j][0]
This is the same only if i == 0, i.e. in the first line.
What you want is
(*arr)[i][j]

It is not really a good idea to hide an array behind a typedef. This is the root of the problem, since arr is actually an array pointer of type uint8_t (*)[4][4]. And when de-referencing an array pointer you have to first take the contents of the pointer to get the array, then after access a specific index. That is, you will have to do (*arr)[i][j] rather than *arr[i][j].
To avoid that fishy syntax in turn, you could use a trick and declare an array pointer to the outermost dimension: uint8_t(*)[4]. Then you can suddenly type arr[i][j] instead. arr[i] then means do pointer arithmetic on a uint8_t(*)[4] type, and then in the obtained result you can access a specific array index, [j].
In addition to the operator precedence issue, you probably want to store data directly into the array. There's no reason why you can't do fread(arr, 16, 1, fp);, since you are using that array in the same order as it is allocated.
I haven't tested it, but you should be able to replace the whole function with this:
void read_block(FILE* fp, uint8_t (*arr)[4][4])
{
const size_t size = sizeof(uint8_t[4][4]);
*arr = malloc(size);
fread(*arr, size, 1, fp);
}

Related

Why are these indices not getting the same thing from a 2d malloc'd C array?

Data file I am reading from:
$ cat temp.txt
0 1 2 3
4 5 6 7
8 9 10 11
C code:
#include<stdio.h>
#include<stdlib.h>
void main(){
int matsize = 12;
int numrows = 3;
int numcols = 4;
int** mat=malloc(matsize*sizeof(int*));
for(int i=0;i<numrows*numcols;++i){
mat[i]=malloc(sizeof(int));
}
FILE *file;
file=fopen("temp.txt", "r");
for(int i = 0; i < numrows; i++){
for(int j = 0; j < numcols; j++) {
if (!fscanf(file, "%d", &mat[i][j]))
break;
}
}
fclose(file);
printf("%d\n",mat[numrows-1][numcols-1]);
printf("%d\n", mat[2][3]);
printf("%d\n", mat[1][5]);
printf("%d\n", mat[0][11]);
printf("Done allocating.\n");
}
$ ./a.out
11
11
0
7
The first two outputs are both 11 as expected. For a 12 item array, I was expecting mat[1][5] and mat[0][11] to output the same thing as mat[2][3] (i.e. the 12th element, i.e. the [i+1th][j+1th] element). My understanding is that internally, the array declared here:
int** mat=malloc(matsize*sizeof(int*));
is not really a 2x3 array, rather it's just a matsize array and that accessing it via mat[i][j] just kind of divides it into [i] rows then gets the [jth] element of the ith row. Does the compiler "know" the array should be a 3x4 array because I am reading the text file in with the line if (!fscanf(file, "%d", &mat[i][j])) ? Does this scanning statement permanently change the mat object into 3 pointers of 4-length integer arrays? Or is it really just still a 12-length array, which should be accessible via dividing into two 6's, one 12, etc (if so, then why didn't the last two indexings print out the right thing)?
Follow up: If I change everything from %d/ints to %lf/doubles, I get this output with the same indexing:
11.000000
11.000000
9.000000
11.000000
Why is, for example, mat[0][11] coming out to 7 when everything is an int, but 11.000000 (as expected) when things are floats?
You should allocate a 2D array instead. It can be done as
int (*mat)[rows][cols] = malloc( sizeof(int[rows][cols]) );
However, to enable the conventient mat[i][j] syntax, you have to drop one of the dimensions in the pointer type:
int (*mat)[cols] = malloc( sizeof(int[rows][cols]) );
Not only does this get rid of the needless complexity and bugs, it also enables you to read the whole file with a single fread call, since you have a real 2D array now, instead of some fragmented pointer-to-pointer thing.
Don't forget the free(mat); at the end.

Dynamically allocating 2d array in c error

My problem is prettty simple, I wanna allocate memory for a 2d array in c, fill it with -1, then free it and exit the program. My code keeps crashing and I dont know what I am doing wrong...
This is what I got:
int main(){
int i,j;
char str1[]="xxxabxcxxxaabbcc";
char str2[]="abc";
int len1=strlen(str1);
int len2=strlen(str2);
printf("%d %d",len1,len2);
//allocate 2d_array
int **H_table = (int**)malloc((len1+1)*sizeof(int));
for (i=0; i<len1+1; i++){
H_table[i] = (int*)malloc((len2+1)*sizeof(int));
}
//fill and print 2d array
for(i=0;i<len1+1;i++){
for(j=0;j<len2+1;j++){
printf("i:%d j:%d",i,j);
H_table[i][j]=-1;
printf(" value:%d\n",H_table[i][j]);
}
}
// free 2d array
for(i=0;i<len1;i++){
free(H_table[i]);
}
free(H_table);
return 0;
}
So what happens is that I wanna allocate an array that has 1 extra line and 1 extra column than the 2 strings if you put them vertically compared to each other.
And this is what I expected( the things in bracets are obviously not part of the table, I put the there for comparison):
(x x x a b x c x x x a a b b c c)
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
a)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
b)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
c)1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
The problem is that the code crashes when it fills the table, and it always crashes for i=9 and j=3, for those specific strings. The weird part is that if you swap the 2 strings(put "abc" in str1) then the code passes the filling stage, and crashes when it tries to free the array.
Sorry for any grammar mistakes or stackoverflow mistakes, I am kinda new here :P
Any idea is welcome :) thx in advance
As a number of people have pointed out, you're allocating H_table with room for len1 + 1 integers but it is actually supposed to be an array of len1 + 1 pointers (to integers). Since pointers are bigger than integers (on your system, anyway), you end up with undefined behaviour from a buffer overrun.
Here's a hint. Avoid this problem, and a variety of other similar issues, by always using the following model for malloc:
some_variable = malloc(n * sizeof *some_variable);
For example:
int** H_table = malloc((len1 + 1) * sizeof *H_table);
for (int i = 0; i <= len1; ++i)
H_table[i] = malloc((len2 + 1) * sizeof *H_table[i]);
That is, let the compiler figure out the right type for the variable (or lvalue). The compiler is less prone to typos than you are, and not writing the type explicitly will make it a lot easier for you to later decide that H_table should have been long or short or unsigned.
For the same reason, don't explicitly cast the return value of malloc. C automatically casts void* to the destination type, and does not provide an error if you manually cast to the wrong type. So just let the compiler do it; it's less typing, safer, and more future-proof.
Note that if you use an expression with sizeof, the compiler does not evaluate the expression [Note 1]. It just figures out the type and substitutes that for the expression. So don't worry about extra evaluation: there isn't any. That's also why it's ok to use this model with declarations, even though some_variable doesn't yet have a value when the malloc is executed.
Notes:
There is one circumstance in which the compiler might evaluate ex in sizeof ex: if ex is a variable-length array. However, in this case ex is always a pointer, so that case cannot apply.
As #xing mentioned in his comment, H_table is a pointer to pointer to integer. so you need to change the int to int* in the first malloc.
here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
int i,j;
char str1[]="xxxabxcxxxaabbcc";
char str2[]="abc";
int len1=strlen(str1);
int len2=strlen(str2);
printf("%d %d",len1,len2);
//allocate 2d_array
int **H_table = (int**)malloc((len1+1)*sizeof(int*));
for (i=0; i<len1+1; i++){
H_table[i] = (int*)malloc((len2+1)*sizeof(int));
}
//fill and print 2d array
for(i=0;i<len1+1;i++){
for(j=0;j<len2+1;j++){
printf("i:%d j:%d",i,j);
H_table[i][j]=-1;
printf(" value:%d\n",H_table[i][j]);
}
}
// free 2d array
for(i=0;i<len1;i++){
free(H_table[i]);
}
free(H_table);
return 0;
}

Matrix with variables in C

I'm going to write in pseudo code to make my question more clear. Please keep in mind this code will be done in C.
Imagine I have an array of any amount of numbers. The first number tells me how big of an array we're dealing with. For example, if my first number is 3, it means I have two 3x3 matrices. So I create two multidimensional arrays with:
matrix1[3][3]
matrix2[3][3]
What I'm having a hard time with is the arithmetic/coding to assign all the numbers to the matrices, I'm having a very hard time visualizing how it would be done.
Imagine a test array contains [2,1,2,3,4,5,6,7,8]
My program should now have two matrixes with:
1 2 5 6
3 4 7 8
Do I need several nested loops? Any help would be appreciated.
At the moment the only idea i get is using two for loops. Or you can make a function and call it every time you need (but don't forget to use k as second argument).
int i, j, k;
/* We start in the 2nd element of the array that's why k = 1. */
k = 1;
/* Now we fill the array1 copying 1 by 1 the elements of the "test array" until
we fill it. Then we do the same with the array2. */
for( i = 0; i < test[ 0 ]; i++ ){
for( j = 0; j < test[ 0 ]; j++ ){
array1[ i ][ j ] = test[ k ]
k++;
}
}
for( i = 0; i < test[ 0 ]; i++ ){
for( j = 0; j < test[ 0 ]; j++ ){
array2[ i ][ j ] = test[ k ]
k++;
}
}
Your data is presented in row-major order. After reading your integer array and validating the content (i.e. the dim=4 means 32 values follow, dim=2 means 8 values follow, etc.) I'm not sure why you want to allocate or loop anything.
I.e. You can use your physical test[] data as the matrices:
int dim = test[0];
int (*mat1)[dim] = (int (*)[dim])(test+1);
int (*mat2)[dim] = (int (*)[dim])(test+1 + dim*dim);
C99 supports variable array declarations at the implementation level (i.e. the compiler can support the feature as it is defined by the standard, but does not have to; see 6.7.6.2 of the C99 standard for more info). If your toolchain does NOT support it, then a predefined macro, __STDC_NO_VLA__ must be defined and can be tested at compile time (see section 6.10.8.3-1 of the C99 standard). That being said, every C99-compliant compiler I've ever used in the last decade-plus does support it, so if your's does not, tell us below in a comment.
If it does, then pay note to the use of 'dim' in the declarations of mat1 and mat2 above). It is one of the few features of C I like that C++ does not have. So dance with the one you brought.
Finally, assuming your compiler is C99 compliant and supports VLAs (__STDC_NO_VLA__ is NOT defined), as an extra super-special bonus it is all-but-guaranteed to be the fastest algorithm to get your two matrices, because there is no algorithm. You read one array element, then assign two pointers. O(3) is hard to beat.
Example
#include <stdlib.h>
#include <stdio.h>
// main loader.
int main(int argc, char *argv[])
{
int test[] = {2,1,2,3,4,5,6,7,8};
int dim = test[0];
int (*mat1)[dim] = (int (*)[dim])(test+1);
int (*mat2)[dim] = (int (*)[dim])(test+1 + dim*dim);
// proof stuff is where it should be.
int i=0,j=0;
for (i=0;i<dim;i++)
{
for (j=0;j<dim;printf("%d ", mat1[i][j++]));
printf (" ");
for (j=0;j<dim;printf("%d ", mat2[i][j++]));
printf("\n");
}
return EXIT_SUCCESS;
}
Output
1 2 5 6
3 4 7 8
A similar test with a 3x3 data set:
int test[] = {3,1,2,3,4,5,6,7,8,9,9,8,7,6,5,4,3,2,1};
Output
1 2 3 9 8 7
4 5 6 6 5 4
7 8 9 3 2 1
And finally, a 4x4 data set:
int test[] = {4,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1};
Output
1 2 3 4 8 7 6 5
5 6 7 8 4 3 2 1
1 2 3 4 8 7 6 5
5 6 7 8 4 3 2 1
The problem with multidimensional arrays in C is that you need to know in advance (at compile time) n-1 of the dimension sizes, they are also a drag when used as function parameters.
There are a couple of alternate approaches:
Creating an array of arrays. i.e. allocating an array of array pointers and then allocating arrays to those pointers.
type **array = malloc(sizeof(type * ) * < firstnumread > );
array[0] = malloc(sizeof(type) * < firstnumread > );
...
Allocating a single dimension array with the size of all the multiplied dimensions. i.e.
type *array = malloc(sizeof(type) * < firstnumread > * < firstnumread >);
In your case, the second is probably more appropiate. Something like:
matrix1 = malloc(sizeof(type)*<firstnumread>*<firstnumread>);
matrix2 = malloc(sizeof(type)*<firstnumread>*<firstnumread>);
Then you can assign values like this:
matrix1[column*<firstnumread> + row] = <value>;
Yes, with 2 for loops.
2D arrays are stored in continuous series of lines from the matrix. So you doesn't even need to allocate new memory you can use your original array. Anyway you can create 2 new standalone array too.
You can crate a function like this, to get the correct number of the matrix.
int getNumber(int array[], int arraynumber, int index_x, int index_y)
{
return array[(((array[0]*index_x)+index_y)+1)+((array[0]*array[0])*arraynumber)];
}
The arraynumber variable is 0 for the first and 1 for the second matrix. This funciton works only if all parameters are correct, so ther is no error detection.
With this function you can easily loop through and create 2 new arrays:
int i,k;
for (i=0; i<array[0]; i++)
{
for (k=0; k<array[0]; k++)
{
newarray1[i][k] = getNumber(array, 0, i,k);
newarray2[i][k] = getNumber(array, 1, i,k);
}
}
Here is something that works in a single loop; no nests and no repeats. I don't know if it'll outperform other answers, but I just felt like giving you a different answer ^_^
I have not tested this code, but it looks like the logic of the algorithm works - that's the point, right? Let me know if it has any errors....
int c=0, x=0, y=0, size=test[0], length=sizeof(test);
for(i=1; i<length; i++) {
if((c-size)<0) {
matrix1[x][y] = test[i];
} else {
matrix2[x][y] = test[i];
}
++y;
if(y%size == 0) {
++c;
y = 0;
x = (c-size)<0 ? ++x : 0;
}
}

Trying to print form array or array addresses...not getting it?

new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.

What is the default value of an array?

I'm creating a table of an arrays where the user can input the value themselves, and I will show them the table of value except the number 0 is use to exit from the scanf
so I don't want number 0 to be store in the array
but I'm seeing number 0 for the next value of an array so I'm wondering if 0 is a default value of an array.
to make it a bit more clear
let say the user entered;
5
4
3
2
1
and 0
so what I suppose to show in my program output is
5
4
3
2
1
which I use array to display the index of 0-4 [1-5]
but just to make sure if number 0 is not store so I call array[5] to see if the next value is 0 or something else and it always display 0 so I want to know if there is a way to make sure that 0 is not going to store in the array
this is what I use to make sure
if(enter != 0){
array[i - 1] = enter;
Sorry if my question is complicated.
Thanks
If the array is with static storage duration it will be initialized to 0. In any other case, elements will not be initialized, i.e. will contain random bits.
Static storage duration have global variables, file scope static variables and block scope static variables.
I revide my answer. Every array that you allocate can contain garbage, or not. The compiler can clear it for you, or not. In your case, I would clear the array with something like -1. Else you will have some undefined values in there, that be 0 or not. It's just not defined, every compiler can behave differently.
Test it:
#include <stdio.h>
void array(void);
int main(void) {
int c[10], i;
printf("Array 1: ");
for(i = 0; i < 10; i++) {
printf("%d", c[i]);
}
printf("\n");
array();
int b[10];
for(i = 0; i < 10; i++) {
printf("%d ",b[i]);
}
printf("\n");
return 0;
}
void array(void) {
int a[10] = {1,2,3,4,5,6,7,8,9,0};
return;
}
It depends, but generally arrays defined at compile-time are full of 0 by default. Arrays defined at run-time not necessarily, they could be 0 or full of crap.

Resources