return of malloc() function - c

malloc() function is said to return a null pointer or a pointer to the allocated space. Suppose for a string we make the statement:
char* ptr = malloc(size)
Isn't ptr a pointer that would point to a pointer?
Isn't :
char** ptr = malloc(size)
supposed to be the correct way to declare the pointer to char?
The compiler however doesn't give a warning when we do either, the warning it does give is for the format specifier if used.
How should we declare this and why? Also, how would char** be used?

No, 'ptr' would contain the pointer returned by 'malloc'. You are assigning the returned pointer, not taking its address.

The char * denotes a char pointer. Malloc will return a void * pointer (that will be automatically converted to whatever pointer you're trying to assign).
The char ** denotes a char * pointer. This is a pointer to a pointer.
If you think of a pointer as a map you have that char * is a map to a char, void * is a map to something mysterious and char ** is a map to another map that leads to a char. So
char* ptr = malloc(size);
Is the correct one, because you want a map to something, not a map to a map.

*ptr is a pointer to a char, which is often used to manage an array
or a string.
**ptr is a pointer to a pointer to a char, which is often used to
manage a matrix (array of arrays) or a string array.

Related

Dereferencing the passed pointer to char array in the function

I have a char array; char students[] = "John Maria Elisa Hans" and a pointer *pStudents pointing to that array. I need to pass this pointer into a function and use there as a char array. What exactly I mean is the pointer needs to be dereferenced in the function to be used as a char array. Indeed, I tried some ways to dereference the pointer, but no result was achieved. How can I achieve it?
Note: passing pointer, not the char array is a must.

How does malloc know which type the returned pointer is pointing at?

I'm learning pointers and memory allocation with C. I've used the snippet below to manually allocate some bunch of bytes to copy:
char *s = get_string("s: "); // this is included in cs50 library and it returns a char pointer
char *t = malloc(strlen(s) + 1); // +1 for "\0"
...
free(t);
My question is this, why do we declare t as it points to a char value? How does malloc know that the pointer t points at a char value, even if we did not enter any "clue" about using char?
It doesn't, and it doesn't need to. malloc allocates a block of exactly as many bytes as you tell it to, and returns a void* pointer to it. The pointer is then implicitly converted to char* when the assignment is made. See this for more insight.

What asterisk position means in C functions building?

I know this is a beginner question, but I can not understand how it works, on every source I find I see a different way to do the same, and I don't understand the difference between these ways to build a function in c which returns a string.
What is happening when:
I write the asterisk after the return type?
char* my_function(){...}
What if write the asterisk before function name?
char *my_function(){...}
What is the asterisk between both?
char * my_function(){...}
What 2 asterisk means?
char **my_function(){...}
And yes, the next code compiles:
char* * **my_function(){...}
OR... are they all the same thing?
char* my_function(){...} defines a function returning pointer to char.
char *my_function(){...} defines a function returning pointer to char. Same as above - different style.
char * my_function(){...} defines a function returning pointer to char. Same as above - different style.
What 2 asterisk means? --> a pointer to a pointer.
char **my_function(){...} defines a function returning pointer to pointer to char. Not the same as above - different return type.
char* * **my_function()(){...} defines a function returning pointer to pointer to pointer to pointer to char. Not the same as above - different return type.
So long as the asterisks lie between char and my_function, the spacing doesn't make any difference.
In all cases they form part of the return type of the function.
char* means the return type is a pointer to a char.
char** means the return type is a pointer to a pointer to a char.
And so on.
In a declaration, T *p, T* p, and T * p are all parsed as T (*p) - the * is part of the declarator, not the type specifier. So the first three function declarations all declare my_function to return a pointer to char.
T **p declares p as a pointer to a pointer to T. Yes, multiple indirection is possible, and you can have pointers to pointers, pointers to pointers to pointers, etc.
Basic rules:
T *p; // p is a pointer to T
T *p[N]; // p is an array of pointer to T
T (*p)[N]; // p is a pointer to an array of T
T *f(); // f is a function returning a pointer to T
T (*f)(); // f is a pointer to a function returning T
T const *p; // p points to a const T
const T *p; // same as above
T * const p; // p is a const pointer to T
The asterisk denotes pointers, they're one of the most important concepts to have a grasp on if you want to be programming in C.
char* is a pointer to a char, char** is a pointer to a char*.
The spacing is irrelevant.
I suggest you take a more in-depth look at pointers, what they are and how to use them.

Can I safely cast a &char[] to char**?

Having the following code:
char data[2048];
And a function declared like this:
int f(char** data);
Can I safely call it like this:
f((char**)&data);
If I just use &data, the compiler issue the following warning:
warning C4047: 'function' : 'char **' differs in levels of indirection from 'char (*)[2048]'
No, you cannot.
data is an array. &data is a pointer to an array. It is not a pointer to a pointer. Despite the fact that data decays to a pointer in multiple contexts, it is not itself a pointer - taking the address gives you the address of the array.
If you want a pointer to a pointer to the array, you might try something like this:
char *pdata = data; // data decays to a pointer here
// (a pointer to the first element of the array)
f(&pdata); // Now &pdata is of type char ** (pointer to a pointer).
though, of course, what you actually need will depend on what your usecase is.
A pointer-to-pointer is not an array, nor is it a pointer to an array, nor should it be used to point at an array. Except for the special case where it can be used to point at the first item of an array of pointers, which is not the case here.
A function int f(char** data); cannot accept a char data[2048]; array as parameter. Either the array type needs to be changed, or the function needs to be rewritten.
Correct function alternatives would be:
int f (char* data);
int f (char data[2048]); // completely equivalent to char* data
int f (char (*data)[2048]); // array pointer, would require to pass the address of the array
As stated in this more detailed example:
While an array name may decay into a pointer, the address of the array does not decay into a pointer to a pointer. And why should it? What sense does it make to treat an array so?
Pointers to pointers are sometimes passed to modify the pointers (simple pointer arguments don't work here because C passes by value, which would only allow to modify what's pointed, not the pointer itself). Here's some imaginary code (won't compile):
void test(int** p)
{
*p = malloc ... /* retarget '*p' */
}
int main()
{
int arr[] = {30, 450, 14, 5};
int* ptr;
/* Fine!
** test will retarget ptr, and its new value
** will appear after this call.
*/
test(&ptr);
/* Makes no sense!
** You cannot retarget 'arr', since it's a
** constant label created by the compiler.
*/
test(&arr);
return 0;
}
You can do something like that.
char data[2048];
char *a=&data[0];
char **b=&a;
f(b);

convert int array to pointer in C

void test()
{
int buf[1000];
//populate buf
foo(buf);//is this correct? Can we pass buf as a pointer that foo expects?
}
void foo(void*ptr)
{}
EDIT:
if foo were fwrite, would the above(mechanism of passing buf so as to supply fwrite with content to write into some file) still be applicable?
Its perfectly valid in C. foo argument is a pointer that can point to any type. When you pass an array, it decays to a pointer pointing to the first element of the array (i.e.,address location of the first element is passed). So,
ptr -> &buf[0] ;
Yes you can do that.
buf is the base pointer of the array.
Yes, You will always pass buf to function as a pointer.
Yes its correct. You can use the "ptr" pointer in your foo function.
http://codepad.org/HwYd0GAh
As the other answers pointed out, yes, you can pass buf to the function.
However, inside the function, the variable ptr has type void*. And there's only a few things you can do with ptr itself. Usually you convert it (with or without a cast) to something relevant, like int*.
void foo(void *ptr) {
int *iptr;
iptr = ptr;
/* now use iptr */
}

Resources