Confusion about array initialization in c language [duplicate] - c

This question already has answers here:
How dangerous is it to access an array out of bounds?
(12 answers)
Closed 3 years ago.
I wrote this code and ran it:
#include <stdio.h>
int i;
int a[] = { 1 };
int main()
{
for (i = 0; i < 10; i++)
printf("%d\n", a[i]);
};
It always gave me the following result
1
0
2
0
0
0
0
0
0
0
I know the length of a[] is 1 and a[1],a[2]... are invalid. But I re-compiled it again and finally I found a[2] always give 2, I am quite confused about the 2, where did it come from and why a[2] is not other numbers such as 0 or some random number?

When you do
int a[] = { 1 };
the number of elements in the array will automatically be adjusted to be equal to the number of elements in the initializer. In this case the initializer contains 1 integer so your code is equivalent to:
int a[1] = { 1 };
You've got an array of length 1 but in the for-loop you are accessing 10 items in it (i.e. accessing a[0], a[1], ... a[9]). This is undefined behavior, and what you are seeing is the data beyond the end of your array.

Related

What does using array index like this [0,1,2] means? [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 6 months ago.
How can an array have an index like [0,1,2]?
And why is [0,1,2]=[2]
Code:
int main(){
int a[]={1,2,3,4,5};
a[0,1,2]=10;
for(int i=0;i<5;i++)
printf("%d ",a[i]);
return 0;
}
Output:
1 2 10 4 5
The comma operator (,) evaluates both expressions and returns the second one (see, e.g., this explanation). I.e., 0,1,2 will evaluate to 2, so a[0,1,2]=10 will result in a[2]=10, which explains the output you get.
a[0,1,2] will be treated as a[2] aka the other indices are ignored.
To test this try: printf("%d ",a[0,1,2]); you will see it prints the
value in index 2 only.
To change the values of multiple indices then you either do it
manually or iterate over them. For example,
a[0] = 10;
a[1] = 10;
a[2]=10;
OR
for(int i = 0; i < 3; i++)
a[i]=10;

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;
}

C: order of evaluation in a conditional expression [duplicate]

This question already has answers here:
Post-increment and Pre-increment concept?
(14 answers)
Closed 5 years ago.
There is the following C code:
#include <stdio.h>
int main ()
{
int a[5] = {0, 1, 2, 3, 4};
int* a_p = a;
float x = 1.5;
while(x > (*a_p++))
{
printf("*a_p = %d\n", *a_p);
}
printf("*a_p = %d", *a_p);
return 0;
}
The question would be which is the result of the final printf statement?
I would judge that the order is:
1) inside while, a_p address is incremented => *a_p is 1 (a[1])
2) 1.5 is compared with 1
3) inside while, a_p address is incremented again => *a_p is 2 (a[2])
4) 1.5 is compared with 2
5) 2 is printed for *a_p
I have tried with 3 compilers and the result is 3.
Why 3 is the correct result? Is first done the comparison and then the pointer is incremented meaning that at step 4 from above, after the comparison is done, *a_p is 3?
Is this always the behavior (is this behavior defined) or is compiler dependent?
Yes that's how post increment works. The while condition is true for 0th and 1th index but when it evaluates to false - the pointer value is already increased as a result it points to index 4 having value 3.
*p++ the value of it will be *p where this p is the old one which is not incremented. Same happens with a_p is here - last time when it is compared the value *a_p++ is 2 but the new value of a_p is pointing to the 4th index. Loop ends and 3 is printed.

Why is the seventh variable 6 in my program?

#include <stdio.h>
int main(void) {
int n,i;
int str[n];
scanf("%d\n",&n);
for(i=0;i<=n;i++)
{
scanf("%d",&str[i]);
printf("%d th %d\n",i,n);
}
return 0;
}
Input:
10
8 9 2 1 4 10 7 6 8 7
Output:
0 th 10
1 th 10
2 th 10
3 th 10
4 th 10
5 th 10
6 th 10
7 th 6
Why is 6 in the output?
This is really strange code with undefined behavior. What do you expect this:
int n; // No value!
int str[n];
To do? You get an array whose length is unknown since n has no value at the point of the str declaration.
If you expected the compiler to "time-travel" back to the str[n] line magically when n is given a value by scanf(), then ... that's not how Co works, and you should really read up on the language a bit more. And compile with all warnings you can get from your environment.
As an extra detail, even if it were fixed so that n had a value, the for loop overruns the array and gives you undefined behavior again.
For an array of size m, the loop header should read
for (size_t i = 0; i < m; ++i)
Since indexing is 0-based, you cannot index at m, that's outside the array.
In your code
int n,i;
int str[n];
you're using n while it has indeterminate value, unitialized. It invokes undefined behavior.
To elaborate, n being an automatic local variable, unless initialized explicitly, contains indeterminate value.
Solution: You need to define int str[n]; after you has taken the value from user (and sanitized).
After that, there's once more issue, your loop runs off-by-one for the array. C uses 0-based array indexing, so, for an array of size n, the valid indexes will be 0 to n-1. You loop construct should be
for(i=0; i<n; i++)
The value for the size of the string str[] is not yet defined. You need to have initialized this value before declaring a string/array.
If you're using gcc to compile, try including the -Wall flag in your compile line to catch errors like this.

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;
}
}

Resources