what is the difference between *p and p[1]? - c

Here is a code for dynamic memory allocation using malloc
void main()
{
int *p,n=5;
p=(int*)malloc(5*sizeof(int));
p[0]=10;
// or *p=10;
p[1]=20
// or *(p+1)=20;
}
As per my knowledge, p is a pointer variable that points to the base address of the allocated memory. If I dont use the * operator, then I can't access the contents pointed to by p. But the statements p[1]=20 and *(p+1)=20
do work the same. Why is this same and also what is the use of * if we can do it this way too p[1]
But then does it also means that when i use malloc the array allocated to the process will have the same name as the pointer used to point the base address

The difference between *p and p[1] is that *p is a pointer that points to the first element of the array, while p[1] is the second element of the array. The difference is that *p gives you access to the entire array, while p[1] only gives you access to the single element.

Related

malloc function return pointer to an array right?

I have a doubt. When malloc() function returns a pointer, is it a pointer to a linear block of memory (similar to array)? Or is it something else?
I would like to know the structure of that memory.
I would like to know the structure of that memory.
There is no structure. Just the memory chunk
(similar to array?)
the memory chunk is exactly the same as array.
The difference is only that reference of that chunk is a pointer.
You cant use `sizeof operator to get the size of that memory chunk.
the reference of the pointer is not the same as reference to the memory chunk. (address of the array always give the reference to first element of the array)
A pointer only points to a single object of the pointed-to type (although that object may be an aggregate type) or function. That object may be the first object in a larger sequence like an array, but you can't know that from the pointer itself. Given code like
char x;
char *p1 = &x;
char *p2 = malloc( sizeof *p2 * 10 );
There's no way to know from the pointers themselves that p1 points to a single standalone object while p2 points to the first in a sequence of objects. You have to keep track of that information separately.
This is true for pointers to aggregate types like
char a[20];
char (*p3)[20] = &a;
char (*p4)[20] = malloc( sizeof *p4 * 10 );
Same deal as above - both p3 and p4 point to a single 20-element array of char. In p4's case, it's pointing to the first in a sequence of 20-element arrays of char, but again you can't know that from the value of p4 itself.
Note that malloc and calloc don't operate in terms of objects, they operate in terms of bytes - you tell them how many bytes of memory you want to reserve, but they have no idea what type of object or sequence of objects is going to occupy that memory. They also need some way to keep track of what's been allocated, so many implementations will reserve some extra memory on each allocation for bookkeeping purposes.
malloc function return pointer to an array right?
size_t n = ...;
void *p = malloc(n);
When the returned pointer is a null pointer, the allocation failed and the pointer should not be dereferenced. It does not need to be free'd.
if (p == NULL) Handle_Failure();
A successful void *malloc(size_t n) call does return a pointer, a void * that can be assigned to any object pointer type. A cast is not needed. p is not a pointer to an array, just a void *. The allocated memory can be the destination of a copy of any object including arrays.
my_type *p = malloc(n);
Use the pointer to store the contents of an array, int, or any object. As long as the initial allocation was big enough, it does not matter. The pointer meets the alignment requirements for all object types. When done, free it exactly once. Then do not use the value in the pointer. Yet p can be re-assigned.
int foo(const struct abc *x) {
struct abc *p = malloc(sizeof *p);
if (p == NULL) {
return 1;
}
*p = *x;
bar(p);
free(p);
return 0;
}
Allocation of 0 bytes is a special case and can be done. Should malloc() return a null pointer or not, the pointer should not be dereferenced. No *p.
Once code gets p, code does not have a portable way to get the size of memory allocated. Code should keep track of the original n as needed. malloc() uses a size_t argument.
Note: free(NULL) is OK
When malloc(); function returns a pointer is it a pointer to a linear blocks of memory
Yes, and it's a void pointer.
(similar to array).
No. It's not an array, or in other words, it's not the pointer to the first element of an array of size passed to malloc(). It's a memory region/ block, virtually contiguous, but the returned pointer (or the variable storing the return value) will not have properties of an array.
would like to know the structure of that memory
If you only want to use the returned memory location, you need not bother. You can just store the returned pointer to a variable of a pointer to complete type, and use that variable to perform operations (read from/ write to) that memory location.
It does not return pointer to an array.
malloc(size_t n) returns a pointer to a contiguous memory location specified by the parameter n.
Note that it is opposed to calloc(size_t nmem, size_t size) which initializes each bit to zero while malloc() leaves the value as indeterminate as suggested in comments.
Default value of malloc
Why malloc may be indeterminate from SO
More about calloc and malloc from SO

How does malloc() know you want to use the block of memory it supplies as an array?

If malloc() returns a pointer to a single block of memory, how can it be used to store multiple values contiguously and allow access to each one using the subscript operator, acting as a pointer to an array?
If I were to try and change the "second element" of an integer by subscripting its address, it would cause undefined behaviour. As malloc() returns the pointer to a single block of memory, shouldn't the pointer it returns refer to the entire block, and thus subscripting it should access the garbage value next to it in memory?
Furthermore, the allocated memory can also be used to store a single value, but only up to the size of the type the pointer is cast to, not to that of the allocated block of memory.
Is all this something to do with the type the pointer is cast to after being returned? Could someone point me in the right direction?
I think your misunderstanding is here:
As malloc() returns the pointer to a single block of memory, shouldn't the pointer it returns refer to the entire block, and thus subscripting it should access the garbage value next to it in memory?
Indeed if you do p = malloc(n) and p has type "pointer to some type of size n", then p[1] is an out-of-bounds array access. However, normally when you do p = malloc(n) to allocate an array, the type of p is not a pointer to the array (of size n), but a pointer to the first element of the array. That is, instead of
char (*p)[500] = malloc(500);
you do:
char *p = malloc(500);
and in this case p[1] is perfectly valid. Note that with the first, unusual, form, you could still do (*p)[1] or p[0][1] and have it be valid.
But be careful, if you use malloc several times it will return memory allocated in different parts of heap. So you can't move around from one array to another.

C pointer concept

I have just started learning c and finding it pretty hard to wrap my head around pointer concept.
I have came across this code samples.
What does below statement mean?
Char *s_item[20];
I know that char *s_item means a character pointer and you need to allocated memory to it before you can assign or copy a string into it. It just stores the beginning address of the string.
Next, what does this statement mean.
s_item=(char(*)20)calloc (30,20);
And lastly can someone explain to me the concept of char **values
I know that it's a pointer to a pointer. But what kind of values we can store in it exactly. Is it a collection of strings?
If you learn about the spiral/clockwise rule you could decipher it as an array of 20 pointers to char. I.e. an array of strings.
Depending on where the definition it, each element will either be null pointers (if it's a global variable) or each element will be uninitialized and have an indeterminate value (if s_item is a local variable). Either way, you must make each pointer in the array point to some valid data before you can really use them, either by making them point to existing strings or by allocating memory dynamically which you then initialize.
As for a pointer to a pointer, it's just the same as any other pointer: It's a pointer that points to something, in this case it's pointing to another pointer.
Example:
char *p = malloc(12); // Allocate 12 bytes and make the variable p point to it
strcpy(p, "hello world"); // Initialize the memory we just allocated with a string
char **pp = &p; // Make the variable pp a pointer, and make it point to the variable p
In memory it looks something like this
+----+ +---+ +---------------+
| pp | --> | p | --> | "hello world" |
+----+ +---+ +---------------+
That is, pp is pointing to the variable p, and p is pointing to memory containing the string "hello world".
The example shown above, having pp is pretty much useless, but with pointers to pointers you can emulate pass by reference with function arguments, and for example do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function(char **pp)
{
*pp = malloc(12); // Allocate memory
strcpy(*pp, "hello world");
}
int main(void)
{
char *p; // Define variable, but don't initialize it
function(&p); // Pass a pointer to the variable p
printf("p = \"%s\"\n", p); // Will print p = "hello world"
}
By passing the pointer to the variable p (using &p) to the function, the function can modify the pointer (i.e. the value of p).
Another use for pointer to pointer is dynamic array of arrays. For example
char **pp = malloc(5 * sizeof(char *)); // Allocate space for five pointers to char
for (size_t i = 0; i < 5; ++i)
{
pp[i] = malloc(12); // Allocate space for a string
strcpy(pp[i], "hello world"); // Initialize the memory
}
Now we have a dynamically allocated array of five dynamically allocated arrays of 12 characters.
Both uses of pointers to pointers works with other data-types than char of course.
It should be noted that even though arrays naturally decays to a pointer to its first element, an array of arrays (like e.g. char x[20][20]) is not the same as a pointer to pointer (e.g. char **). For an explanation of this see e.g. this old answer of mine.
char *s_item[20];
The statement above means "s_item" is an array and its elements are pointers to characters.
s_item=(char(*)20)calloc (30,20);
Something seems wrong with your code. First, (char(*)20) is the forced casting but I think it should be (char*). Second, this is an invalid assignment because you want to assign a char* to a char**.
"calloc" is a C function for dynamic memory allocation. The function returns a (void*), which means a pointer to unknown. And the pointer is cast into a pointer to char*. But it cannot be assigned to s_item because s_item is a pointer to pointer to character.
As for the third question, if the type of a variablepp is char**, we can store an address in pp, which means pp is a pointer. And the address stored in pp must be the address of another pointer which points to a character. So we call pp is the pointer to pointer to character.

Variable Pointer vs Memory Pointer

What is the difference between the two, a ptr pointing at a variable and a ptr pointing at memory? I know a pointer is a variable that holds the memory address of a variable. So... A ptr pointing at a variable holds the address of that variable whereas a ptr pointing at memory is directly pointing at memory? The first somehow still holds some information about the initial variable whereas the later only knows an address?
EDIT: I didn't mean for this question to cause so much controversy and I'm not entirely sure why it's getting downvoted. I'm just trying to understand pointers... After doing some reading on the linked 'duplicate' it is my understanding that a ptr pointing to a variable always references that variable, cannot be reassigned, and cannot point to other pointers, and share an address with the variable. Memory pointers can point to NULL, can be reassigned, can point to other pointers, and have their own memory address. Are these true for C or only C++
A pointer is a variable whose value is an address in memory. The pointer also knows the type of whatever it's pointing to (or else it's a void*).
Basically that's all there is to it. There is no fundamental distinction between a "pointer that points to a variable" and a "pointer that points to memory". Whatever the pointer points to is in memory in any case. Whether the pointer points to a char variable, or a double variable, or an object, it's always simply pointing to the memory location where that char/double/object is stored.
Here's the way I see it, and I'll go by example.
In C, a pointer variable can be declared as:
char* p;
Then you can reserve stack memory for your program via a char array like so:
char buffer[5000];
You can then make the pointer reference this memory block like so:
p=buffer;
Variables by default point to their own addresses in stack memory for fast access. If you want to assign a pointer to memory from the heap, you can use calloc() or malloc(). For example, this code:
char* m;
m=malloc(5000);
... allocates 5000 bytes of memory from the heap (aka extended memory). then when you make reference to that pointer, you're actually reading to and writing from RAM.
This prints the letter "A" to the same static memory location twice then reads it back:
char block[10];
char* p=block;
block[0]='A'; //write to 1st position of block memory
*p='A'; //write same value to 1st position of block memory again
char *r;
r=p;
printf("%c",*r);
And now the same program but this time using just memory from the heap:
char* block;
block=malloc(10);
char* p=block;
block[0]='A'; //write to 1st position of block memory
*p='A'; //write same value to 1st position of block memory again
char *r;
r=p;
printf("%c",*r);
free(block);
please note that i am still learning and some information might be wrong
ok for example lets make
int i = 5;
int *ptr = &i;
lets say memory address for those are
i = 0x0001
ptr =0x0002
in those memory address are
0x0001 = 0101 // this is 5 for binary
0x0002 = 0x0001 //this is the address of 'i'
so when ptr is called in these kind of ways u get these values
ptr = 0x0001 // the address stored in ptr
*ptr = 0101 // the * means whatever is at the address stored in ptr
if i had wrote like this
int i = 5;
int *ptr = *i;
then ptr will have whatever is at 'i'
i = 0x0001
ptr = 0101
so if i call ptr again in these ways
ptr = 0101
*ptr // this will not work cus 0101 is not a memory address
edit
Also on your edit u said "that a ptr pointing to a variable always references that variable, cannot be reassigned, and cannot point to other pointers, and share an address with the variable."
This is not true for C, a pointer can be reassigned whenever u want and can point to other pointers
Unless it was made as a
const int *ptr = &i;
Then the pointer can not be changed later
Also u said "memory pointers can point to NULL, can be reassigned, can point to other pointers, and have their own memory address"
This is true as I said above but there are no such thing as a memory pointer and a variable pointer, there is only pointer that can hold a memory address.

I need a greater understanding of what a pointer actually points to

What is the actual value of pointer:
char *ptr;
And it's pointing to a memory address, correct?
Not yet; it's uninitialized.
What you're asking is like asking what number int i; refers to.
I will try to explain in a simple way, (sorry if my English is not god enough i am learning)
Let say you have an array of characters:
char a[5];
Then you want to create a pointer to the address of the first element:
char *p = &a[0];
Now since the name of an array is a synonym for the location of the
initial element you can rewrite to the following statement:
char *p = a;
Now here is where magic takes place, as the previous character pointer points to the address of the first element you can do stuffs like the following:
instead of getting the 'i'-th element from a[i], you can move the pointer 'i' places to reference the address of the value contained in the 'i'-th position and then get it's value:
char value = *(a + i);
Font(The C programming language 2nd Edition, Chapter 5)
char *ptr;
It is not pointing any memory address until it is initialized;
But you can use it to point an address.
Suppose,
int i=0;
i has an address in memory. if it become 0xFFFF0 then when you write
ptr=&i;
then your pointer points to address 0xFFFF0 .
now suppose,
int array[5]={0}; is an array.
then if you write-
ptr=array;
then ptr points to the starting address of array because array name is an address.
Yes, it is pointing to the address of the variable.
The variable might be on the stack if the variable is declared inside a function, or at the top of RAM if declared at the top level.
As the other answers point out, you haven't made it point to anything yet, so dereferencing the pointer will likely result in a segmentation fault.
You need to do something like
char ch;
char *ptr = &ch;

Resources