#Understanding array pointers

60 messages · Page 1 of 1 (latest)

tall gorge
#

I am trying to learn about array pointers and would like to clarify a concept -

int arr[2] = {5,8};
int *arr_ptr = arr;

Are operations on arr_ptr and arr going to be the same from now? For instance, if I do *(arr+i) or (*(arr_ptr + i)), will they give be the same? The output is the same when I run it.

obsidian mantleBOT
#

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.

cyan cipher
#

& will be different, for instance.

#

For normal element accesses arr_ptr might be used as well as arr sure.

gilded dome
#

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

tall gorge
#

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;
cyan cipher
#

We do not need to cast.

gilded dome
#

I'm not sure how accurate this is, but I've heard that it is in fact a bad practice to do so

tall gorge
#

But my book says we need to cast :/

#

Because calloc will return a void pointer

gilded dome
#

the cast will be done implicitly

tall gorge
#

Ah I see

#

Thank you

obsidian mantleBOT
#

@tall gorge Has your question been resolved? If so, type !solved :)

tall gorge
#

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

}
cyan cipher
#

They are indeed the same.

tall gorge
#

Thank you

eternal hazel
tall gorge
eternal hazel
tall gorge
#

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.

eternal hazel
#

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;
}
simple hullBOT
#
Program Output
0x1c8f2a0
0x1c8f2a4
0x1c8f2a8
eternal hazel
#

^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 index i
I'm not sure what you mean by "where the pointer is". Do you mean that the type of the pointer can be void *, or are you saying that p is 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.

tall gorge
#

Thank you

eternal hazel
#

;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;
}
simple hullBOT
#
Program Output
0x5a32a0
0x5a32a0
0x5a42d0
tall gorge
#

Even if the allocator is able to expand the block, it'll still point to the start of the block right?

eternal hazel
#

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

eternal hazel
tall gorge
#

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.

eternal hazel
#

Feel free to ask more if you have any other questions

tall gorge
#

Thank you so much

eternal hazel
#

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.

tall gorge
#

Thank you

obsidian mantleBOT
#

@tall gorge Has your question been resolved? If so, type !solved :)

tall gorge
#

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?

gilded dome
#

the call to realloc frees ptr

tall gorge
#

Makes sense

#

Thank you

#

Do you see anything else wrong with the code?

gilded dome
#

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

tall gorge
#

Thank you

eternal hazel
#

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);
}
simple hullBOT
#
Compiler Output
<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