Why printing a static 2D array in C gives me seg fault? - c

I just want to print out a static array (2D array) in C using functions. I use gcc as my compiler. When I try to run my code it gives me a seg fault and I dont have any idea why:
#include <stdio.h>
void print_out_an_array(int n, int m, int tab[n][m])
{
int i,j;
for(i=0; i<n; i++)
for(j=0; j<m; j++)
printf("tab[%d][%d] = %d\n", i, j, tab[i][j]);
}
int main(int argc, char **argv)
{
int tab[2][4] = {{1,2,3,4}, {5,6,7,8}};
print_out_an_array(tab, 2, 4);
return 0;
}

your function call and function definition doesnt match
your function call
print_out_an_array(tab, 2, 4);
but in function definition your first argument is int
void print_out_an_array(int n, int m, int tab[n][m])
make the arguments same, like:
change function call to
``print_out_an_array(2, 4, tab);`
update:
check this code it works
and also read this for reference C, passing 2 dimensional array

In your function definition, first parameter is int type but you are calling your function with first argument as int **. Change your function call to
print_out_an_array(2, 4, tab);
About the question in your comment:
Ok, but how about this code: http://ideone.com/Z4mHkb why it gives me an error?
Function parameters **tab and tab[n][m] are not equivalent. Compiler, on seeing tab [m][n] as function parameter, interprets it as
void fun(int (*)[m]tab, int n, int m)
i.e , it interprets tab as a pointer to an array of m integers. While on seeing int **tab, it simply interprets tab as a pointer to a pointer to integer (or an array of pointers ( int *tab[]) to int ).

Instead of answering the original solution whose solution is obvious, I answer the other one from your comment.
Your array is a
int[][N]
while you pass a
int ** to your function.
These are completely different from each other:
An int[][N] has all values from all dimensions beneath each other.
An int **, however, points to one or more pointers, in turn pointing to the real values.
At int[][], you can omit one level of indirection and can turn it into a
int (*)[N]
i. e. a pointer to an array. This array must be of determined size, which isn't fulfilled in your case as well.

Related

how to pass 2d array address to a function and write on it and print it in calling function

I have a function that simply takes 2d char array write on first element [0][0] to n and m element and in main I like to print what has been written. I only need to pass the address of entire two dimensional array and use it in calling function.
This is what I tried so far with multiple variations of tries but nothing seems to work
folloing code cause segFault
I got segFault at array[0][0]='c'; in the called function. please note I need to pass only the address of 2d array so I can easily move around and populate the array in called function.
void bps(char **array,int m, int n)
{
array[0][0]='c';
}
I also tried like this *array[0]='c'; but no luck so far
I am passing array like bps(array,x,y); in main
this is the code in main
int main()
{
int x=3,y=3;
char array[3][3]={"ab","ax"};
// Or should I use like this
// char array[3][3]=(char [3][3]){"ab","ax"};
bps(array,x,y);
printf("%c",array[0][0]);
return 0;
}
or should I use like this in bps(..)
void bps(char *array,int m, int n )
{
*(*(array))='c';
}
please clarify
char** may be used for 1D arrays of pointers, such as pointing in the first item in an array of strings. But it cannot be used to point at a 2D array. Forget that you ever heard of type** in relation to 2D arrays.
Change void bps(char **array,int m, int n) to:
void bps (int m, int n, char array[m][n])
Access individual items with array[i][j], not with obscure and unreadable pointer arithmetic like *(*(array))='c';.
Detailed explanation:
The reason why char array[m][n] works is that arrays, whenever used as a function parameter, get implicitly adjusted ("decays") to a pointer to their first element by the compiler.
Given an array char array[m][n], it is an array of arrays. The first item is therefore an array of type char[n]. A pointer to that first item type is written as char (*)[n]. Therefore
void bps (int m, int n, char array[m][n])
is 100% equivalent to
void bps (int m, int n, char (*array)[n])
And in either case the array is passed "by reference", not by value as one might incorrectly suspect.

Matrix pointer in C

I will go straight to what I'm asking for, I also see some similar question but is not what I'm looking for...so it seems I have to ask with a new forum.
I'm preparing myself for a future examination, where is not required the pointer, but I would like to get some extra information and abilities.
Here's the code followed by the question...
I'm using Fedora 33, I know is different from some IDE on Windows (ex: Visual Studio or Dev C++)
/* It's just a simple test, if this work I will get myself into a more complicated one, as you could read in the
* forum, I'm getting ready ( just a recheck of my abilities ) for an universitary examinaton. */
#include <stdio.h>
#include <stdlib.h>
#define N 5
void casual_generation(int** mat);
void prompt_print(int** mat);
int main()
{
int **mat[N][N];
casual_generation(**mat);
prompt_print(**mat);
}
void casual_generation(int** mat)
{
int i=0,j=0;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
mat[i][j] = rand() % 50;
}
void prompt_print(int** mat)
{
int i=0,j=0;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
Somebody else on the forum used malloc, struct or other stuff, as you can see in this picture, when I try to execute him it says "Segmentation fault (core dumped)"
screen error
Where is my error?
And if you want, can you also send me the version with the passed value pointer?
Thanks for whoever will give me an answer, and time dedicated.
This declaration
int **mat[N][N];
does not make a sense. It means that you have a matrix elements of which are pointers of the type int **. But you need a matrix elements of which are integer numbers of the type int. That is you need a declaration like this
int mat[N][N];
So now you have a two-dimensional array (or matrix) of integers.
As you are going to pass this two-dimensional array to functions then used as an argument expression it is converted to pointer to its first element of the type int ( * )[N].
Correspondingly the functions that accepts such an array should be declared like
void casual_generation( int mat[][N], size_t n );
void prompt_print( int mat[][N], size_t n );
or (that is fully equivalent) like
void casual_generation( int ( * mat )[N], size_t n );
void prompt_print( int ( *mat )[N], size_t n );
because the compiler adjusts function parameters having array types to pointers to array element types.
Now for example the first function can be defined the following way
void casual_generation( int ( * mat )[N], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
mat[i][j] = rand() % 50;
}
}
}
And the function can be called like
casual_generation( mat, N );
A similar way can be defined the function prompt_print.
Using the second parameter makes the function more general. For example it can be called for two-dimensional arrays with different numbers of rows.
Now I will explain why you are getting a segmentation fault in your original code.
You have this declaration
int **mat[N][N];
a two dimensional array of pointers of the type int **.
Then you are using the expression **mat as an argument of function calls like this
casual_generation(**mat);
Then you are applying the dereference operator like *mat the array designator is converted to pointer to its first element (row) having the type int ** ( * )[N]. So dereferencing this pointer you get the first row of your array int **[N]. Applying the second time the dereferenced operator to this expression that has an array type the used expression is again is converted to pointer to its first element of the type int **( * ). That is it points to the first element of the first row of the original two-dimensional array. Dereferencing this pointer you get the first element of the type int **. This uninitialized pointer with indeterminate value the function accepts as its argument.
Thus dereferencing this first uninitialized element of the original matrix within the function
mat[i][j] = rand() % 50;
^^^
you get a segmentation fault. The reason of the fault is the incorrect matrix and the corresponding function parameter as it was shown above in tbe beginning of the answer.
Where is my error?
The "Segmentation fault" error happens because you define the variable mat as a pointer, but don't allocate any memory for it to point to.
int **mat[N][N];
You meant to do
Int mat[N][N];
and
casual_generation(mat);
prompt_print(mat);
By passing **mat you are passing mat[0][0] that is an int, but you want to pass the whole matrix which is a pointer to pointers to int (i.e. int **)
And you may want to introduce srand() in your code.
Just to make things clear:
mat is of type int ** and it's the whole matrix (or if you want it's a pointer to the first row)
*mat is of type int * and it's the first row of the matrix (or if you want it's a pointer to the first element of the first row)
**mat is of type int and it's the first element of the first row of the matrix
int **mat[N][N];
Here, you defined a double pointer to a 2D array. You only need to use one of those - a double pointer or a 2D array, like so:
int mat[N][N];
However, the bigger problem comes from trying to interchange 2D arrays and double pointers. This isn't possible in C since the 2D array is laid out flat in memory.
You need to create an array mat_ptr of pointers yourself and then pass that to casual_generation and prompt_print.
Finally, these casual_generation and prompt_print functions expect to be given a pointer, so you shouldn't dereference the pointer with ** before calling the function.
The final working code is:
int main()
{
int mat[N][N];
int *mat_ptr[N];
for (int i = 0; i < N; i++)
mat_ptr[i] = mat[i];
casual_generation(mat_ptr);
prompt_print(mat_ptr);
}
As you can find a detailed explanation why the code crashed in the other answer I will only propose a quite elegant solution that uses a neat though little known feature from C99 called Variable Length Arrays (aka VLA).
#include <stdio.h>
#include <stdlib.h>
void casual_generation(int n, int mat[n][n]);
void prompt_print(int n, int mat[n][n]);
int main()
{
const int N = 5;
int mat[N][N];
casual_generation(N, mat);
prompt_print(N, mat);
}
void casual_generation(int n, int mat[n][n])
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mat[i][j] = rand() % 50;
}
void prompt_print(int n, int mat[n][n])
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
It compiles in pedantic mode with no warnings and it works like a charm.
VLA were introduced to C to simplify numerical computation over multidimensional arrays.

How to get the array size in a function without any additional arguments

main()
{
int arr[] = {1, 2, 3, 4};
function(arr);
}
int function(int a[])
{
}
Here I want to get the length of the array which was not initialized. The main function in my case is which I do not have any idea..assume I am getting the array elements from some other program.
Arrays decay to pointers when used as arguments to a function:
int function(int a[]);
and
int function(int *a);
are the same.
This means that you cannot know how many elements are in an array that is passed to your function unless you have a separate parameter that indicates the length of the array.
You can find out how many elements there are in arr in main() by sizeof(arr)/sizeof(arr[0]).
However, you cannot use this method in that function(). Because in this case a is a pointer to int, you need to pass the length of a as an extra argument to function(), like this:
int function(int a[], int len) {
You can't.
The function just receives a pointer (an address to a location in memory).
You have two options: pass the lenght of the array as an extra argument to the function (as other suggested)...
...or establish a convention (if possibile) where a certain value on the array represent the last element (so you can get the length by counting elements until the end-of-array item).
That's what happens with C strings. A C string is an array of chars where a character with value of 0 indicates the end of the string.
#include<stdio.h>
int ArraySize (int *);
main ()
{
int array[] = {1,2,3};
printf("The size of the array is%d \n", ArraySize(array));
}
int ArraySize (int *a)
{
for (int i=0; a[i]!='\0'; i++);
return i;
}

How to use an array pointer in a function?

I had to write a program which has a function that sums all positive number in an array, but using function parameter array as an pointer. There in main function a problem occurs, when i try to call sum function. here is my source code:
#include <stdio.h>
#include <conio.h>
int posit(int *x[], int n){
int s=0;
for(int i=0; i<n; i++){
if(*x[i]>0){
s=s+*x[i];
}
}
return s;
}
int main(){
int k;
scanf("%d",&k);
int a[k];
for(int i=0; i<k; i++){
scanf("%d",&a[i]);
}
int b=posit(&a,k);
printf("%d\n", b);
getch();
return 0;
}
When an array is passed to a function it decays to a pointer to its first element. Change the signature of the function to:
int posit(int* x, int n){ /* Equivalent to 'int posit(int x[], int n)' */
and change the element access syntax of the array in the function from *x[i] to just x[i]. The invoke the function:
int b=posit(a,k);
Another point worth mentioning is to check the return value of scanf(), which returns the number of assignments made, to ensure &a[i] is actually being assigned and the program is subsequently not using uninitialized variables.
You may find the Arrays and Pointers section of the C FAQ useful.
Actually in your example you are passing to function pointer to pointer (please note that similar notation is very often used with main argument char *argv[]).
As mentioned in hmjd post while passing array to function this is converted to address of its first element. Instead of explicitly using pointer (int *x) you can also use array notation (int[] or even int[k]) but those are the same.
Please also note that in second method (int[k]) size provided doesn't matter and inside function it will be not known. This is only important to include size when you are dealing with multiple dimension arrays, but this is other story...
From K&R2
When an array name is passed to a function, what is passed is the
location of the initial element. Within the called function, this
argument is a local variable, and so an array name parameter is a
pointer, that is, a variable containing an address.
So you will be passing only the first element to the function.
Once this is understood your source can be modified as follows
int posit(int *x, int n)
and to call this function from main you can use
int b=posit(a,k); //Note only the location of the first element is being passed

incompatible pointer type

I just started programming so pointers and arrays confuse me.
This program just assigns random numbers from 0 - 9 into array and prints them out
(#include <stdio.h> #include <stdlib.h> #include <time.h>)
int function(int *num[]){
int i;
for(i=0; i<10; i++){
srand((unsigned)time(NULL));
*num[i] = rand()%10;
printf("%d", *num[i]);
}
return 0;
}
int main(){
int num[10];
function(&num); // incompatable pointer type (how do i fix this?)
return 0;
}
Thankyou
Change your code to read something like this:
int function(int num[]){
int i;
for(i=0; i<10; i++){
srand((unsigned)time(NULL));
num[i] = rand()%10;
printf("%d", num[i]);
}
return 0;
}
int main(){
int num[10];
function(num);
return 0;
}
In main(), you are allocating an array of 10 integers. The call to function(num) passes the address of this array (technically, the address of the first element of the array) to the function() function. In a parameter declaration, int num[] is almost exactly equivalent to int *num (I'll let you ponder on that one). Finally, when you access the elements of num[] from within the function, you don't need any extra *. By using num[i], you are accessing the i'th element of the array pointed to by num.
It may help to remember that in C, the following are exactly the same:
num[i]
*(num+i)
You don't need to pass in a pointer to your array. Just pass in the array. I have fixed your pointer code below.
Also, you should not reset the seed (srand) through every iteration through the for loop.
int function(int num[]){
int i;
srand((unsigned(time(NULL));
for(i=0; i<10; i++){
num[i] = rand()%10;
printf("%d", num[i]);
}
return 0;
}
int main(){
int num[10];
function(num);
return 0;
}
It all depends on what you want to achieve in the end.
(1) If your function function is intended to be used with arrays of run-time size, then you have to pass a pointer to the first element of the array. That is achieved by the following equivalent declarations
int function(int *num)
or
int function(int num[])
Inside the function you have to access the passed array as
num[i] = rand() % 10;
And you call your function as
function(num);
Of course, when the array size is a run-time value, it makes sense to pass that size to the function as well, meaning that your function should have the following interface
int function(int num[], size_t n)
And implement it for an array of size n, instead of hardcoding 10 directly into your implementation.
(2) If your function function is intended to be used with arrays of fixed compile-time size (10 in this case), then the better approach would be to pass a pointer to the entire array. It is achieved by the following declaration
int function(int (*num)[10])
Inside the function you have to access the passed array as
(*num)[i] = rand() % 10;
And you call your function as
function(&num);
So it is either (1) or (2).
What you currently have in your code looks like a mix of these two approaches. More precisely, you code looks like an attempt to implement the second approach, but it is missing some important parentheses :)
Most answers given to you so far suggest using the first approach. However, seeing that the array size is actually a compile-time constant in your case, I would suggest sticking with the second approach.
Use either int *num or int num[], don't use both together as you have right now (int *num[]). An array is passed to a function as a pointer to the first element, i.e. int *num, which is equivalent to int num[].

Resources