#Understanding array pointers
60 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
& will be different, for instance.
For normal element accesses arr_ptr might be used as well as arr sure.
also, sizeof will be different. arrays contain information about their size and thus the number of elements in an array can be found. when an array decays to a pointer, this information about the number of elements is lost
I have another question
int *ptr = (int *)calloc(num_elements, sizeof(int));
Why do we need to typecast the output of calloc over here? Doesn't calloc just return the address of the beginning of an array?
For instance, we don't typecast while doing this -
int arr[2] = {5,8};
int *arr_ptr = arr;
We do not need to cast.
I'm not sure how accurate this is, but I've heard that it is in fact a bad practice to do so
the cast will be done implicitly
@tall gorge Has your question been resolved? If so, type !solved :)
In the below program, why does the author do &p[i]. Since p is a pointer, won't p+i be enough? Or are they the same -
#include<stdio.h>
#include<stdlib.h>
void main()
{
int i,n;
int *p;
printf("Enter value of n: ");
scanf("%d",&n);
p=(int*)calloc(n,sizeof(int));
printf("Enter values\n");
for(i=0;i<n;i++)
scanf("%d",&p[i]);
for(i=0;i<n;i++)
printf("Square of %d = %d\n", p[i],
p[i] * p[i]);
free(p);
}
They are indeed the same.
Thank you
In my uni I've somehow ended up having a discussion about the merits of &p[i] versus p+i a few times.
I personally like &p[i] since I read it out loud as "the address of the element at index i", but some others prefer p+i for its shortness.
But at the end of the day the compiler will generate identical machine code for this, so just pick one and consistently use it per project. :)
I’d like to do that. However, in cases where you don’t know where the pointer is pointing (such as in realloc), the only option is &p[i]
How come? &p[i] is identical to &(*(p + i)), and because & and * cancel each other out, that's identical to p + i
Doesn't (p+i) imply that you know where the pointer is currently and then you add i to its current location? Whereas &p[i], I believe you don't need to know where the pointer is. The only information you need is the index i. I am a C newbie, so I could be completely wrong.
So looking at your code, you have this:
int *p;
p = (int *)calloc(n, sizeof(int));
In C I recommend just letting it implicitly convert void * to int * for you:
int *p;
p = calloc(n, sizeof(int));
So if you do p + 2 after these lines, what you are saying in C with that is that you want to take whatever value is in p, which is in this case an address (just a word for an index into your GBs large array of bytes called RAM)
Because C can see that p is a pointer, it will interpret p + 2 as p + 2 * sizeof(int) for you, because the pointer is pointing to an array of integers. The reason C does this implicitly is because you could otherwise get a pointer that points halfway an integer, which'd cause chaos if you tried to read that value.
;compile -Wall -Wextra -Werror -Wfatal-errors
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *p = calloc(1, sizeof(int));
printf("%p\n", p);
printf("%p\n", p + 1);
printf("%p\n", p + 2);
return 0;
}
0x1c8f2a0
0x1c8f2a4
0x1c8f2a8
^note how the addresses go up by 4 every time, since the size of an int on this machine is apparently 4 bytes
Whereas
&p[i], I believe you don't need to know where the pointer is. The only information you need is the indexi
I'm not sure what you mean by "where the pointer is". Do you mean that the type of the pointer can bevoid *, or are you saying thatpis allowed to be uninitialized, or something else? I think you're mistaken, but if you can find an example, you can show what you mean.
Ah, I think I was mistaken before. Somy confusion came from the use of realloc. During realloc , the existing array is either extended or a new array is created. I thought that the realloc pointer in the case of the existing array would point to the beginning of the extended block. But now I see I am wrong.
Thank you
It all depends on whether the allocator is able to expand the block or whether it gets blocked. Look closely at the addresses here:
;compile -Wall -Wextra -Werror -Wfatal-errors
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int *p = calloc(1, sizeof(int));
printf("%p\n", p);
p = realloc(p, sizeof(int) * 2);
printf("%p\n", p);
p = realloc(p, sizeof(int) * 100);
printf("%p\n", p);
return 0;
}
0x5a32a0
0x5a32a0
0x5a42d0
Even if the allocator is able to expand the block, it'll still point to the start of the block right?
So the first calloc() call only asked for 4 bytes, but it was able to grow into an 8 byte block without issue anyways, since there was apparently nothing else allocated that was in the way of expansion
But when you ask to grow to 400 bytes, then it does decide to move the block somewhere else, but the exact reason why it chooses to or chooses not to is an implementation detail of the specific allocator you use. You can even replace malloc() with your own variant, if you wanted to, and some people do to squeeze extra performance out with their specific niche
If by "the block" you mean the original one before the realloc() call, then no, that isn't guaranteed, as seen by the 3rd print.
But if you are asking whether a pointer returned by malloc()/calloc()/realloc() always points to the first byte of the array, then yes, that's guaranteed.
Thank you.
Just to confirm that we are all on the same page, realloc regardless of whether it extends an existing block or creates a new block will point to the beginning of the array.
Yup!
Feel free to ask more if you have any other questions
Thank you so much
If you're trying to learn C, I can highly recommend clicking the Compiler bot, and clicking the big + Add App to add it to your own server. Creating your own server only takes a few minutes, and it's a great playground for testing things, being very easy to try stuff out with on your phone.
Thank you
@tall gorge Has your question been resolved? If so, type !solved :)
Why am I getting this statement - free(): double free detected in tcache 2
I used free twice as I had 2 pointers -
#include <stdio.h>
#include<stdlib.h>
int main()
{
int num;
printf("Enter the size of the array you want");
scanf("%d", &num);
int *ptr = (int *)malloc(num*sizeof(int));
for(int i = 0; i<num; i++){
printf("Enter the value at index %d\n", i);
scanf("%d", (ptr+i));
}
for(int i = 0; i<num; i++){
printf("The value at index %d is %d\n", i, *(ptr+i));
}
int new_num;
printf("Enter the new size of the array you want");
scanf("%d", &new_num);
int *new_ptr = (int *)realloc(ptr, num*sizeof(int));
for(int i = num; i<new_num; i++){
printf("Enter the value at index %d\n", i);
scanf("%d", (new_ptr+i));
}
for(int i = num; i<new_num; i++){
printf("The value at index %d is %d\n", i, *(new_ptr+i));
}
free(ptr);
free(new_ptr);
}
Also, is the above code looking correct?
the call to realloc frees ptr
Ah!
Makes sense
Thank you
Do you see anything else wrong with the code?
when you realloc, you use num instead of new_num
thus you have UB in your third for loop
also, there's quite a few redundant parenthesis and casts although these don't techincally affect correctness
Thank you
Make sure to always compile with at least these flags, so the compiler can point the issues out for you:
;compile -Wall -Wextra -Werror -fsanitize=address,undefined
#include <stdio.h>
#include<stdlib.h>
int main()
{
int num;
printf("Enter the size of the array you want");
scanf("%d", &num);
int *ptr = (int *)malloc(num*sizeof(int));
for(int i = 0; i<num; i++){
printf("Enter the value at index %d\n", i);
scanf("%d", (ptr+i));
}
for(int i = 0; i<num; i++){
printf("The value at index %d is %d\n", i, *(ptr+i));
}
int new_num;
printf("Enter the new size of the array you want");
scanf("%d", &new_num);
int *new_ptr = (int *)realloc(ptr, num*sizeof(int));
for(int i = num; i<new_num; i++){
printf("Enter the value at index %d\n", i);
scanf("%d", (new_ptr+i));
}
for(int i = num; i<new_num; i++){
printf("The value at index %d is %d\n", i, *(new_ptr+i));
}
free(ptr);
free(new_ptr);
}
<source>: In function 'main':
<source>:28:5: error: pointer 'ptr' used after 'realloc' [-Werror=use-after-free]
28 | free(ptr);
| ^~~~~~~~~
<source>:20:27: note: call to 'realloc' here
20 | int *new_ptr = (int *)realloc(ptr, num*sizeof(int));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
Build failed