I have some code that looks like this:
int *array[10];
printf("%p\n", array); // Prints an address
printf("%p\n", *array); // Prints a different address
printf("%d\n", **array); // Segmentation Fault 11
printf("%d\n", *array[0]); // Segmentation Fault 11
printf("%d\n", (*array)[0]); // Segmentation Fault 11
Why do I get a segmentation fault? Shouldn't it print the first value in the first array?
To take a closer look, understand the nature of the declaration:
int *array[10];
This declares an array of 10 pointers (currently uninitialized) to ints -- note that this is not the same as a pointer to an array of 10 ints, which would instead be declared int (*array)[10]. Even declared this way though, you'd still need to initialize the pointer with something.
printf("%d\n", array); // Prints an address
This prints an the address of the ages array (the array is converted to a pointer automatically by passing it to printf).
printf("%d\n", *array); // Prints a different address
This uses the same rules to convert the array to a pointer, and then dereferences that pointer. Therefore, you're printing the first value of the array (equivalent to printf("%d\n", ages[0])). However, what you're actually printing here is an address, not an integer (even if it is uninitialized).
printf("%d\n", **array); // Segmentation Fault 11
printf("%d\n", *array[0]); // Segmentation Fault 11
printf("%d\n", (*array)[0]); // Segmentation Fault 11
Each of these are now dereferencing the uninitialized pointer stored in array[0]. They do indeed be refer to an int, but the pointer to that int is whatever the compiler and/or your OS decided to put in there.
Example: Pointer to an array
An example of using a pointer to an array looks like this:
#include <stdio.h>
int main()
{
int array[10] = { 1,2,3,4,5,6,7,8,9,10 };
int (*parr)[10] = &array;
printf("%p\n", parr);
printf("%p\n", *parr);
printf("%d\n", **parr);
printf("%d\n", *parr[0]);
printf("%d\n", (*parr)[0]);
}
Output (addresses vary, obviously)
0x7fff5fbff990
0x7fff5fbff990
1
1
1
The last three all ultimately lead to the same element, but go about it in different ways.
You get a segmentation fault because you are attempting to dereference an uninitialized pointer, which is Undefined Behavior.
This command (and all following):
**ages
Dereferences the array (which decays to a pointer), which you then dereference. You have an array of pointers, not a pointer to an array.
int *array[10];
array is array[10] of pointer to int (note that [] has higher precedence than *). But none of these 10 pointers have been initialised to point to valid location.
Given that,
printf("%d\n", array); // address of array itself (also address of first element)
printf("%d\n", *array); // getting the value of the fisrt array element - UB/unitilialise (currently points to some random location)
printf("%d\n", **array); // dereference that first pointer - UB/segfault as deferencing an initialised pointer
printf("%d\n", *array[0]); // same as *array
printf("%d\n", (*array)[0]); // same as **array
#include <iostream>
using namespace std;
#include <math.h>
#include <string.h>
int main() {
int arr[5] = {1,2,3,4,5};
int *p=arr;
int intgerSize=sizeof(int);
for(int k=0;k<5;k++)
{
cout<<"arr ["<<k<<"] "<<*(p+(k*sizeof(int)/intgerSize));
cout<<" "<<(p+(k*sizeof(int)/intgerSize));
cout<<" "<<p+k<<"\n";
}`enter code here`
return 0;
}
OUTPUT:-
arr [0] 1 0x7ffd180f5800 0x7ffd180f5800
arr [1] 2 0x7ffd180f5804 0x7ffd180f5804
arr [2] 3 0x7ffd180f5808 0x7ffd180f5808
arr [3] 4 0x7ffd180f580c 0x7ffd180f580c
arr [4] 5 0x7ffd180f5810 0x7ffd180f5810
Related
In Visual Studio 2019, I tried to assign value to int pointer at specified position, but it doesn't work. Is this possible?
Moreover how I can printf a pointer's value, and not the address?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p =(int*)calloc(10,1);
p[0]=1;
p[1]=0;
p[2]=1;
printf("%d\n",p);
}
Thank
calloc(10,1) allocates 10 single byte items not 10 integers. So (except 8 bits uCs where int is 2 bytes) your allocated memory area is far too short. if you want to allocate space for 10 integers you need to int *p = calloc(10, sizeof(*p));
printf("%d", p) invokes an UB as p is the reference (address) stored in the pointer p. You need to dereference the pointer to get the integer referenced (pointed) by the p pointer printf("%d\n, *p);
To print the reference stored in the pointer you need to use the correct format: printf("%p\n", (void *)p);.
It works.
To print the value you need to derreference with * or index with [].
printf("%d\n",*p); //p[0]
printf("%d\n", p[0]); //p[0]
printf("%d\n",*(p + 1)); //p[1]
printf("%d\n", p[1]); //p[1]
Please explain (reason for the output) what happens as a result of running the two segments of code. Please explain their difference too. There are two versions of setArr(int, int) as explained below...
#include <stdio.h>
void setArr(int, int);
int *arr[10]; // array of 10 int pointers
int main(int argc, char *argv[]) {
int i;
setArr(0, 0);
setArr(1, 100);
setArr(2, 200);
setArr(3, 300);
setArr(4, 400);
for (i = 0; i < 5; i++)
printf("arr[%d]: %d\n", i, *arr[i]); /* should be 0,100, 200,300,400 */
return 0;
}
Versions of setArr
Version A
void setArr(int index, int v) {
int i = v;
*arr[index] = i;
}
Output: Segmentation fault (core dumped)
Version B
void setArr(int index, int v) {
int i = v;
arr[index] = &i;
}
Output:
arr[0]: 400
arr[1]: 32748
arr[2]: 32748
arr[3]: 32748
arr[4]: 32748
I presume the values from running Version B are just random values.
I am fairly new to pointers I have knowledge in Java, so please explain it as beginner friendly as you can :)
You are hitting a lot of undefined behavior scenarios, but I will explain what is likely happening.
arr is an array of 10 pointers to integers.
int * arr[10]; // array of 10 int pointers
And when declared as a global variable, all of those pointers are going to be zero-initialized - so hence, it's an array of 10 NULL pointers.
So this line in version A, is dereferencing the address at arr[index]:
* arr[index] = i;
Is effectively saying this:
*(NULL) = i;
And that will certainly crash consistently.
In Version B, you have it as:
int i = v;
arr[index] = &i;
So now you are correctly assigning a pointer to a slot in the array. However that address getting assigned is to a local stack variable, i, which goes out of scope as soon as the function returns. So when you print the value at that address, it's most certainly been clobbered from other calls writing on top of the stack. (Or technically this "undefined behavior" of accessing a memory address of a stack variable that has gone out of scope.)
Better:
void setArr (int index, int v){
arr[index] = malloc(sizeof(int));
*arr[index] = v;
}
The above allocates memory for the address that you want to copy that value into. You're on your own for how to free that memory.
Alternatively:
Just declare arr as an array of integers instead of pointers:
int arr[10];
void setArr (int index, int v){
arr[index] = v;
}
And then print normally without the * deference thing on arr.
printf("arr[%d]: %d\n", i, arr[i]);
Version A says "the contents of an undefined pointer equals i" - undefined behavior = crash. Basically you are trying to write to some unknown location in memory.
Version B says "Some pointer = some address" - still undefined behavior as &i goes out of scope, but it is still an address and so it "kind of works". Here you are writing to "good" memory locations, but reading from bad ones.
in first case, you have defined the "array of pointers" to integer. They are not integer pointers. Either you will have to allocate memory (preferably using melloc/calloc functions) before storing any value to them OR you can define the array of integer like this:
int (*a)[10]
The following link may show you some idea about it: Difference between *ptr[10] and (*ptr)[10]
In second case, you are saving the address of integer into integer pointer, which is ok, but int i is local variable to function setArr(). This will therefore, the value of int i will be dereferenced every time the function setArr() exits. Therefore you are getting undefined behavior for 2nd case. Either you can use static int i OR use global variable (not preferred) OR use pointer to integer assignment.
I know there are many similar questions, but I can't find an answer.
When passing the two-dimensional [3] [4] array to the function in my code below, how does the compiler know how far to increment the pointer, in the case of the last printf() where we are incrementing 3 x 4 memory locations, if the number 3 is missing in the function argument?
I mean, why is only arr [] [4] sufficient and not [3] [4]? Thanks
#include <stdio.h>
#include <stdlib.h>
int Fun(int arr[][4])
{
printf("%p\n", arr); // address of first element
printf("%p\n", arr[0] + 1); // address increments by 4, pointing to next "inner array"
printf("%p\n", arr + 1); // how does it know to increment address by 3 x 4 here? The complete array size
}
int main()
{
int arr[3][4] =
{
1,2,3,4,
5,6,7,8,
9,10,11,12
};
printf("%p\n", arr);
printf("%p\n", arr[0] + 1);
printf("%p\n", arr + 1);
printf("Passing to function\n");
Fun(arr);
return 0;
}
First, Fun should be defined with:
int Fun(int arr[][4])
rather than what you have, int Fun(int* arr[][4]);.
Next, when Fun(arr) is evaluated, arr is automatically converted from an array of 3 arrays of 4 int to a pointer to an array of 4 int. Similarly, in the declaration of Fun, int arr[][4] is automatically adjusted to be a pointer to an array of 4 int. So the argument type and the parameter type will match if you declare Fun correctly.
You could also declare Fun as:
int Fun(int (*arr)[4])
This is the same thing as above, due to the automatic adjustment that would be applied to the declaration above. Note that the asterisk here is grouped with the arr by the parentheses. This makes it a pointer to an array of int, rather than an array of pointers to int.
Now, as to what will be printed, in main:
printf("%p\n", arr);
In this statement, arr will be automatically converted to a pointer to its first element, so it becomes a pointer to an array of 4 int. Then the value of this pointer is printed. Note: When printing pointers, technically you should convert them to const void * or void *, as with printf("%p\n", (const void *) arr);. However, omitting this likely does not cause a problem at the moment.
printf("%p\n", arr[0] + 1);
In this statement, arr[0] is the first element of arr. That first element is an array of 4 int, and it is automatically converted to be a pointer to its first element. So arr[0] becomes a pointer to the first int. Then adding 1 advances the pointer to the next int. The result is likely an address four bytes beyond arr, depending on your C implementation. (It could be a different number of bytes, but four is the most common today.)
printf("%p\n", arr + 1);
In this statement, arr is converted to a pointer to its first element, an array of 4 int. Adding 1 advances to pointer to the next element, which is the next array of 4 int. So this likely adds 16 bytes to the address.
Then, in Fun:
printf("%p\n", arr); // address of first element
Here arr is a pointer to an array of 4 int. Its value is printed, yielding the same address as for the corresponding printf in main.
printf("%p\n", arr[0] + 1); // address increments by 4, pointing to next "inner array"
Here arr[0] is the object pointed to by arr, which is an array of 4 int. Since it is an array, it is automatically converted to a pointer to its first element, which is an int. So this points to the first int. Then adding 1 advances to the next int, and this again yields the same address as the corresponding printf in main.
printf("%p\n", arr + 1); // how does it know to increment address by 3 x 4 here? The complete array size
In this case, arr is a pointer to an array of 4 int, and adding 1 advances it to the next array of 4 int, so the result is likely 16 bytes beyond the value of arr, and this again yields the same address as the corresponding printf in main.
If you saw different values for the printf statements in Fun and main, this was likely because of the incorrect declaration with int* and because int * is eight bytes in your C implementation, compared to four for int. That error would have doubled some of the increments. You should not have seen any multiple of three in the increments.
Regarding the first dimension, Fun does not need to know the first dimension because it never advances any pointers by units of the first dimension. It receives only a pointer to an array of 4 int, and it does not need to know that there are 3 such arrays there.
The detailed answer by Eric Postpischil clearly shows all the issues in OP's code.
I'd like to note that passing a pointer to the correct type would let the compiler doing the right pointer arithmetic:
#include <stdio.h>
#include <stdlib.h>
void Fun(int (*arr)[3][4])
{
printf("Address of the first element: %p\n", (void *)*arr);
printf("Address of the second row: %p\n", (void *)(*arr + 1));
printf("Address after the last element: %p\n", (void *)(arr + 1));
}
void Fun_vla(size_t rows, size_t cols, int (*arr)[rows][cols])
{
printf("Address of the first element: %p\n", (void *)*arr);
printf("Address of the second row: %p\n", (void *)(*arr + 1));
printf("Address after the last element: %p\n", (void *)(arr + 1));
}
int main()
{
int arr[3][4] =
{
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
Fun(&arr);
puts("");
Fun_vla(3, 4, &arr);
return 0;
}
I have this code, Which uses function to which a pointer to an array is passed
#include<stdio.h>
void func(int ptr[][3])
{
printf("%d %d",*ptr,*ptr+1);
}
void main()
{
int arr[2][3]={{1,2,3},{4,5,6}};
int (*ptr)[3]=arr;
func(ptr);
}
Now, If I pass the actual array name to the function as
#include<stdio.h>
void func(int ptr[][3])
{
printf("%d %d",*ptr,*ptr+1);
}
void main()
{
int arr[2][3]={{1,2,3},{4,5,6}};
int (*ptr)[3]=arr;
func(arr);
}
Both of the above code executes and prints the same address. But what is the point of having a pointer if array name of multi-dimensional array does the same job.
Or is there any difference between them?
This:
printf("%d %d",*ptr,*ptr+1);
...isn't doing what I'd guess you intend it to. In particular, the precedence means that *ptr+1 means the same as (*ptr)+1, whereas I'd guess what you really wanted was:
*(ptr + 1)
To get an idea of the real difference between the two, it might make more sense to not dereference the pointers at all, and just print out the addresses:
void func1(int *a) {
printf("%p %p\n", (void *)a, (void *)(a+1));
}
void func2(int ptr[][3]) {
printf("%p %p\n", (void *)ptr, (void *)(ptr+1));
}
int main() {
int x[] = {1, 2, 3};
printf("sizeof int == %d\n\n", (int)sizeof(int));
func1(x);
func2(&x);
}
Now let's look at the result:
sizeof int == 4
0x7ffe3f67ba20 0x7ffe3f67ba24
0x7ffe3f67ba20 0x7ffe3f67ba2c
The first shows addresses ending in f00 and f04. As shown, sizeof(int) == 4, so we're seeing pretty much what we expect--adding 1 to an int * yields a pointer to the next int, so the address is increased by 4.
In the second case, the addresses end with a20 and a2c, so we're seeing a difference of c (12 decimal). In this case, it's not a pointer to an int--it's a pointer to an array of three ints. So, when we add one, the address changes by the size of an array of three ints of 4 bytes apiece (i.e., 3x4 = 12).
But what is the point of having a pointer if array name of multi-dimensional array does the same job.
The point is that an array is something completely different than a pointer and of course, you could have a pointer without an array.
The array holds many objects of the same type in a contiguous memory region. So pointer vs array makes a (huge) difference for the declaration.
Taking a pointer of an array just to pass it along is not necessary because that happens automatically in C. It doesn't hurt either.
#include<stdio.h>
void foo(int **arr) {
arr[1][1]++;
}
main() {
int arr[20][20];
printf("%d\n",arr[1][1]);
foo((int**)arr);
printf("%d\n",arr[1][1]);
}
Suppose you declare:
int arr[ 10 ][ 20 ] ;
What type is arr?
You may think that it's int **, but that's incorrect.
Its actually of type int (*)[20] when it decays (like when you pass it to a function);
Array decaying applies only once.
Details here
Now consider the following,
#include<stdio.h>
#include<stdlib.h>
void foo(int arr[][20]) {
arr[1][1]++;
}
main() {
int (*arr)[20];
arr = malloc(sizeof(int (*)[]) * 2); //2 rows & malloc will do implicit cast.
printf("%d\n",arr[1][1]);
foo(arr);
printf("%d\n",arr[1][1]);
}
Output :
$ gcc fdsf.c && ./a.out
0
1
arr and arr+1 are pointing to array of 20 integers.
arr + 0 --> int int int ... int (20 ints, contiguous)
[0][0] [0][1]
arr + 1 --> int int int ... int (20 ints, contiguous)
[1][0] [1][1]
Here's what an int[2][2] looks like in memory:
int[2] int[2]
That is, an array immediately followed by another array.
Here's what an int[2] looks like in memory:
int int
That is, an int immediately followed by another int.
So, here's also what an int[2][2] looks like in memory:
int int int int
^ ^
| |___ this is arr[1][1]
|
|____ this is p[1], assuming sizeof(int*) == sizeof(int)
If you cast arr to an int**, I'm going to call the result p. Then it points to the same memory. When you do p[1][1] you don't get arr[1][1]. What the program does instead is, it reads the value at p[1], adjusts that up by the size of an int, and dereferences it. If that second int contained, say, the value "21" then you have just tried to dereference the pointer "25" (if int is 4 bytes). That ain't right.
Arrays are not the same as pointers, and 2-D arrays are certainly not the same thing as pointers-to-pointers.
Because foo expect a pointer to a pointer to int and you are passing it a pointer to an array of 20 int. Casting it won't change the fact that it isn't the correct type.
If you change it like this, you get the expected result:
#include<stdio.h>
void foo(int arr[][20]) {
arr[1][1]++;
}
int
main() {
int arr[20][20];
arr[1][1] = 1;
printf("%d\n",arr[1][1]);
foo(arr);
printf("%d\n",arr[1][1]);
}
foo needs to know the array size (well, at least the second array dimension, first isn't needed), otherwise it can't do the necessary pointer arithmetic for the [1][1].
Problem is that int arr[20][20] for 2d array means that this array is stored as 1d array, and lines are stored one after other. when you do indexing to int **arr you actually take 2nd element from first line of array, then you dereference it and take first element there.