Why the following code is giving segmentation fault error
#include<stdio.h>
int main()
{
int i;
int a[2][2]={1,2,3,4};
int **c;
c=a;
for(i=0;i<4;i++)
printf("%d",*(*(c)+i));
}
This assignment:
c=a;
Should give you a warning. a decays into a pointer to its first element, which has type int (*)[2]. Assigning that type to a variable of type int ** requires an explicit cast.
Redeclaring c should fix your problem:
int (*c)[2];
Example warning from clang:
example.c:8:6: warning: incompatible pointer types assigning to 'int **' from
'int [2][2]' [-Wincompatible-pointer-types]
c=a;
^~
1 warning generated.
Read the comments of the following code:
#include<stdio.h>
int main()
{
int i;
int a[2][2]={{1,2},{3,4}}; // Put each dimension in its braces
/*int a[2][2]={1,2,3,4};
This declaration of array make the following:
a1[ONE] a2[TWO] THREE FOUR
a3[Unknown value] a4[Unknown value]
i.e. the numbers 3 and 4 are being written beyond of the array...
*/
int *c1;
int **c2; // `int **` is a pointer to a pointer, so you have to
c1=&a[0][0]; // declare a pointer `c1` and then assign to it `c2`.
c2=&c1; // AND use `&` to assing to pointer the address of
// variable, not its value.
for(i=0;i<4;i++)
printf("%d",*(*(c2)+i)); // here is `double dereference` so here must be `c2`
// (ptr-to-ptr-to-int) but not c1 (ptr-to-int).
return 0; // AND make the `main()` to return an `int` or
// make the returning type `void`: `void main(){}`
// to make the `main()` function to return nothing.
}
This is a problem in the definition of c. int **c; Suggests that this is a pointer to a pointer, but the definition of a is of type int *[2]. Changing the definition of c to int (*c)[2] should do the trick.
Related
New learner here; I am performing a traverse on any given array but I find I get this error:
exe_3.c:18:27: warning: incompatible pointer types passing 'int *' to parameter of type 'int **' [-Wincompatible-pointer-types]
int result = traverse(&arr[6], &n);
^~~~~~~
exe_3.c:4:25: note: passing argument to parameter 'A' here
const int traverse(int *A[], int *N){
What I have tried:
#include <stdio.h>
#include <stdlib.h>
const int traverse(int *A[], int *N){
int i = 0;
int arr[*N];
while(i < *N){
arr[i] = *A[i];
i += 1;
}
return *arr;
}
int main(){
int arr[6] = {1, 2, 3, 4, 5, 6};
int n = sizeof(arr)/sizeof(arr[0]);
int result = traverse(&arr, &n);
printf("%i\n", result);
return EXIT_SUCCESS;
}
Your call traverse(&arr, &n); passes a pointer to the array arr to the function traverse.
You get the error message, because the correct type definition for a pointer to an array of integers is int(A*)[]. You have that type in the definition of the traverse function incorrect (your line 4).
You will see that this is not enough to compile your code. When accessing the elements of such an array via that pointer you need the expression (*A)[i]. You have that access in the implementation of the traverse function incorrect (your line 8).
See also here for more details: C pointer to array/array of pointers disambiguation
What I find also strange with your traverse function is that the array arr is not used completely. Only the first value is returned. I suppose your code is just not complete.
today i started learning C, and i got stucked in function pointers. This is my code:
main.c:
#include <stdio.h>
int sumOfElements(int *arr, int arr_elements);
int main()
{
int (*ptr)(int,int) = NULL;
ptr = sumOfElements;
int a[] = {128, 64, 32, 16, 8, 4, 2, 1};
printf("Total of price is: %d", ptr(a, 8));
}
int sumOfElements(int *arr, int arr_elements)
{
int k =0;
int total;
for(;k < arr_elements;k++)
{
total += arr[k];
}
return total;
}
What i'm trying to do is access the elements of the array in the sumOfElements functions. When i call it normally, then everything goes smooth. When i try to use the function pointer, then the compiler throw me some warning before, and then the Segmentation Fault error:
main.c:17:9: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
main.c:19:41: warning: passing argument 1 of ‘ptr’ makes integer from pointer without a cast [-Wint-conversion]
main.c:19:41: note: expected ‘int’ but argument is of type ‘int *’
Segmentation fault (core dumped)
Since i'm still learning it, i'm unsure about touching the code, because, like i said before, it works without the function pointer. Now, the error main.c:17:9: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types], i didn't really understand it, because they're both int. So, if you could explain that too, it would save me a lot of time. So, why does it only throw Segmentation Fault (core dumped) when i use the funptr? All i know is that the Segmentation error is when we try to access memory that is only read-only or it's out-of-bound
For starters the pointer is declared like
int (*ptr)(int,int) = NULL;
that is it is a pointer to a function with two parameters of the type int.
But the function sumOfElements have different types of parameters
int sumOfElements(int *arr, int arr_elements);
That is the first parameter has the type int * instead of int.
Also as the array is not changed within the function then it is better to declare the function like
long long int sumOfElements( const int *arr, size_t arr_elements);
The function return type is long long int instead of int because it decreases the risk of overflow of the sum of elements of the array.
Correspondingly the pointer shall be declared like
long long int (*ptr)( const int *, size_t ) = NULL;
and the function should be called like
printf("Total of price is: %lld", ptr(a, sizeof( a ) / sizeof( *a ) ) );
Within the function you forgot to initialize the variable total.
int total;
The function can be defined the following way
long long int sumOfElements( const int *arr, size_t arr_elements )
{
long long int total = 0;
while( arr_elements-- )
{
total += arr[arr_elements];
}
return total;
}
Your function pointer declaration is of incorrect type.
Your pointer has signature of int (*ptr)(int,int) = NULL; while your function is int ()(int *, int).
Try declaring your pointer as int (*ptr)(int *,int) = NULL;
The function pointer needs to have the same parameter and return types as the function itself. In your ptr declaration you declare the first argument as int, but it should be int*.
int (*ptr)(int*,int) = NULL;
You have to use int (*ptr)(int*,int) = NULL; instead of int (*ptr)(int,int) = NULL;, since your array is an int pointer.
As your regular function sumOfElements already receives an int pointer it works correctly.
I wanted to ask how to get rid of warning that says assignment from incompatible pointer type.
This is the code I use:
#include<stdio.h>
int main()
{
int a2d[2][2]={{1,2},{3,4}};
int **pa;
pa=a2d;
}
And getting this:
7:5: warning: assignment from incompatible pointer type pa=a2d;
When this
pa=a2d;
executes, compiler shoots the warning/error(depends upon whether you are using -Werror or not) as
main.cpp:7:8: error: cannot convert 'int [2][2]' to 'int**' in assignment
7 | pa=a2d;
| ^~~
| |
| int [2][2]
and this error is valid as a2d is two dimensional array, that doesn't mean its of int** type, similar to the concept of array is not pointer.
To make things works pa should be pointer to an array not double pointer int**. For example
int a2d[2][2]={{1,2},{3,4}};
int (*pa)[2] = a2d; /* pa is pointer to an array */
here pa can point to 2 elements at a time i.e pa points to a2d[0] base address and pa+1 will points to a2d[1] base address.
You are probably looking to decay your 2d array to array of pointers to array elements. In this case:
int a2d[2][2] = { { 1,2 },{ 3,4 } };
int (*pa)[2] = a2d;
To access 4:
printf("%d\n", pa[1][1]);
Your assignment is wrong, you can't parse 2d array to pointer to pointer.
Your code should like this:
#include<stdio.h>
int main()
{
int a2d[2][2]={{1,2},{3,4}};
int * pa;
pa=&a2d[0][0];
}
Becasue 2d array isn't double pointer. But this works:
#include<stdio.h>
int main()
{
int ad[2]={4,5};
int * pa;
pa=ad;
}
But it's passing its address. But if you write:
int a2d[2][2]={{1,2},{3,4}};
int ** pa;
pa=a2d;
It passing address of a2d array to double pointer...
My code needs to pass an array to a void pointer (The struct has (void *) that cannot be modified). The two versions of code below produce the same output but the latter has two warnings. My question is which of the two methods is preferred? Is there a way to typecast to remove the warnings?
This version does not have warnings and produces the output as expected:
#include <stdio.h>
void test(void *var_arr, char var_1);
typedef struct {
char chip;
void *buffer;
}test_struct;
int main()
{
int test_array[3] = {3,7,5};
char var_1 = 0x20;
printf("Hello, World!\n");
test(&test_array, var_1);
return 0;
}
void test(void *var_arr, char var_1)
{
int i;
test_struct var_ts;
var_ts.chip = var_1;
var_ts.buffer = var_arr;
for (i=0; i<3; ++i)
printf("\nThe data values are : %X \n\r", *((int *)var_ts.buffer+i));
}
Hello, World!
The data values are : 3
The data values are : 7
The data values are : 5
This version below has two warnings but compiles and produces the output expected:
Warning(s):
source_file.c: In function ‘main’:
source_file.c:17:10: warning: passing argument 1 of ‘test’ from incompatible pointer type
test(&test_array, var_1);
^
source_file.c:3:6: note: expected ‘int ’ but argument is of type ‘int ()[3]’
void test(int *var_arr, char var_1);
#include <stdio.h>
void test(int *var_arr, char var_1);
typedef struct {
char chip;
void *buffer;
}test_struct;
int main()
{
int test_array[3] = {3,7,5};
char var_1 = 0x20;
printf("Hello, World!\n");
test(&test_array, var_1);
return 0;
}
void test(int *var_arr, char var_1)
{
int i;
test_struct var_ts;
var_ts.chip = var_1;
var_ts.buffer = (void *)var_arr;
for (i=0; i<3; ++i)
printf("\nThe data values are : %X \n\r", *((int *)var_ts.buffer+i));
}
The lower version tells you what the problem was in the first one: passing a pointer to the array instead of a pointer to the first element.
Passing a pointer to the array, which has the type int(*)[3]:
test(&test_array, var_1);
Passing a pointer to the first element, which has the type int*:
test(test_array, var_1);
The code happens to work because the two pointers points to the same address, so the pointer to the array appears to work, but the code is still undefined.
Passing a pointer to the first element is correct, as the array test_array, which has the type int[3] decays to type int* when it is passed to the function.
The warnings are shown because the compiler does static analysis on the code and identified a possible cause of bugs.
When using the void pointer the compiler cannot do this static analysis since it does not know what type is used.
If the datatype is known I would always prefer using this type as pointer instead of the void pointer. I would only use the void pointer when it is acceptable that the pointer can point to anything. In the end this is about personal taste and the code guidelines you follow.
I'm new in programming and learning pointers in array in C. Have a look at the below programmes.
1st program
#include<stdio.h>
int fun();
int main()
{
int num[3][3]={21,325,524,52,0,6514,61,33,85};
fun(num);
printf("%d",*(*(num+1)+1));
*(*(num+1)+1)=0;
printf("%d",*(*(num+1)+1));
return 0;
}
int fun(int **p)
{
*(*(p+1)+1)=2135;
return 0;
}
2nd program
#include<stdio.h>
int fun();
int main()
{
int num[3][3]={21,325,524,52,0,6514,61,33,85};
fun(num);
printf("%d",*(*(num+1)+1));
*(*(num+1)+1)=0;
printf("%d",*(*(num+1)+1));
return 0;
}
int fun(int *p)
{
*((p+1)+1)=2135;
return 0;
}
3rd program
#include<stdio.h>
int fun();
int main()
{
int num[3][3]={21,325,524,52,0,6514,61,33,85};
fun(num);
printf("%d",*(*(num+1)+1));
*(*(num+1)+1)=0;
printf("%d",*(*(num+1)+1));
return 0;
}
int fun(int (*p)[3])
{
*(*(p+1)+1)=2135;
return 0;
}
In the first program **p is used in the fun() function which I think it should be correct and in that function I've written *(*(p+1)+1) to change the first element of first array. But on compiling this program it's showing error: invalid type argument of unary '*' (have 'int'). As far as I know num is a pointer to array and it is holding the address of num[1] which is again holding the address of num[1][0].
On compiling the second program compiler is showing no error. And *((p+1)+1)=0 is changing the value of 2nd element of first array. Why it is changing the value of 2nd element of zeroth array not the value of first element of first array? and How? It should be *(*(p+1)+1)=0.
In the third program the compler is showing no error and it is showing the correct result. How?. What does *(p)[3] mean?
I had searched about this but couldn't found the satisfactory result.
All of your programs are ill-formed. Your compiler must produce warning or error messages, and the output of any executable produced is meaningless.
They are ill-formed because int[3][3] is not compatible with int **, nor with int *, nor with int *[3].
To pass int[3][3] to a function, the function must accept int (*)[3] and nothing else (well, except for void *).
This is because arrays can be converted to a pointer to the first element of the array. (In C syntax, num can be used to mean &num[0]).
In C, there are only truly one-dimensional arrays; an array of type int[3][3] is considered to be an array of 3 elements, each of which is an array of 3 ints.
So a pointer to the first element of num is a pointer to an array of 3 ints, which is written as int (*p)[3]. You could write:
int (*p)[3] = &num[0];
or the shorthand for the same thing:
int (*p)[3] = num;
NB. You continually write *(*(num+1)+1)) which is difficult to read. Instead of this, num[1][1] seems much clearer.
In C, x[y] is always exactly equivalent to *(x+y).
I think you are asking: What's the difference between
int fun(int *p)
and
int fun(int (*p)[3])
The first one expects a pointer to an int. The second one expects a pointer to an array of 3 ints.
You are able to call to both these functions using num since you declared the function as
int fun();
If you declare the functions like they are defined, you will get compiler error/warning for the first version.
Here's an updated version of your code and the resulting compiler warning, using gcc and compiler flag -Wall.
#include <stdio.h>
int fun(int *p);
int main()
{
int num[3][3]={21,325,524,52,0,6514,61,33,85};
fun(num);
return 0;
}
int fun(int *p)
{
*(p+0)=2135;
return 0;
}
test.c: In function ‘main’:
test.c:7:4: warning: missing braces around initializer [-Wmissing-braces]
test.c:7:4: warning: (near initialization for ‘num[0]’) [-Wmissing-braces]
test.c:8:4: warning: passing argument 1 of ‘fun’ from incompatible pointer type [enabled by default]
test.c:3:5: note: expected ‘int *’ but argument is of type ‘int (*)[3]’