C - proper syntax for pointer - c

I call a function global var as follow:
char *Pointer;
I then pass it into function:
char *MyChar = DoSomething (&Pointer);
which is defined as:
char *DoSomething (char *Destination)
{
free (*Destination);
//re-allocate memory
Destination = malloc (some number);
//then do something...
//finally
return Destination;
}
it only works if I use (*Destination) instead of (Destination). can someone tell me if that is correct? I still do not understand why it does not take (Destination).

It is correct, Destination is already declared as a pointer, so you pass the address of Destination in DoSomething(&Destination), that is like a pointer to pointer, then you need to dereference Destination inside DoSomething() function, for which the indirection operator * works.
But the right way, is not to pass the address of the pointer, but the pointer instead like in
DoSomething(Destination);
now, since you want to malloc Destination inside the function, you should the do this
char * DoSomething( char **Destination )
{
// free( Destination ); why?
//re-allocate memory
*Destination = malloc( some number );
//then do something...
//finally
return *Destination;
}
this is a demonstration of how you can use pointers
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *copyString(const char *const source)
{
char *result;
int length;
length = strlen(source);
result = malloc(length + 1);
if (result == NULL)
return NULL;
strcpy(result, source);
printf("The address of result is : %p\n", result);
printf("The content of result is : %s\n", result);
printf("The first character of result is # %p\n", &result[0]);
return result;
}
int main()
{
char *string = copyString("This is an example");
printf("\n");
printf("The address of string is : %p\n", string);
printf("The content of string is : %s\n", string);
printf("The first character of string is # %p\n", &string[0]);
/* we used string for the previous demonstration, now we can free it */
free(string);
return 0;
}
if you execute the previous program, you will see that the pointers both point to the same memory, and the contents of the memory are the same, so calling free in main() will realease the memory.

Here is a correct approach
char *Pointer;
//,,, maybe allocating memory and assigning its address to Pointer
//... though it is not necessary because it is a global variable and
//... will be initialized by zero. So you may apply function free to the pointer.
char *MyChar = DoSomething( Pointer );
char * DoSomething( char *Destination )
{
free( Destination );
//re-allocate memory
Destination = malloc( some number );
//then do something...
//finally
return Destination;
}
As for your code then
Type of the argument does not correspond to type of the parameter in function call
char *MyChar = DoSomething (&Pointer);
the type of the parameter is char * ( char *Destination ) while the type of argument is
char ** ( &Pointer )
As Destination is a pointer then instead of
free (*Destination);
you have to write
free( Destination );

It's because you are passing in an address of the pointer char *Pointer with the line
char *MyChar = DoSomething (&Pointer);
Since you are passing in the address of the pointer in your function DoSomething it sees the functional scope variable Destination as a pointer to an address that is the address of the pointer Pointer.
So rather than passing in the address of Pointer with
char *MyChar = DoSomething(&Pointer);
you need to pass in the pointer itself like so:
char *MyChar = DoSomething(Pointer);
which will allow you to use
free(Destination);
Notice the lack of & indicating the address of Pointer.

Related

Using double pointers in C

Am doing a task where am supposed to used getline function read input from a user from the terminal. Here is my code:
int main(int ac, char **av)
{
printf("Write something: \n");
char **buf = NULL;
size_t buf_size = 0;
ssize_t bytes_read = getline(buf, &buf_size, stdin);
if (bytes_read != -1)
write(STDOUT_FILENO, buf, buf_size);
else
printf("An error occured\n");
free(buf);
return (0);
}
From the code above. My program displayed the text: An error occurred.
Did some code refactoring and this is what I came up with:
int main(int ac, char **av)
{
printf("Write something: \n");
char *buf = NULL;
size_t buf_size = 0;
ssize_t bytes_read = getline(&buf, &buf_size, stdin);
if (bytes_read != -1)
write(STDOUT_FILENO, buf, buf_size);
else
printf("An error occured\n");
free(buf);
return (0);
}
Voila! The code displayed whatever was inputted, just what I wanted. So I fixed my the issue. But what am trying to understand is what's wrong the first code snippet? An it is right to do this?:
char **name = "John Doe";
or
char **name = NULL;
I did some quick test on an online compiler. Here is the code:
int main() {
// Write C code here
char **name = "John Doe";
printf("%p\n", name); //0x55f5f9890004
printf("%p\n", *name); //0x656f44206e686f4a
printf("%c\n", *name); //J
printf("%p", "John Doe"); //0x55f5f9890004
return 0;
}
I realised that the double pointer was just treated as a single char pointer. Not sure if my finding are right. If you can give a better explanation the above main function that would be cool.
When you want to change a variable in a function you need to pass it by reference. Otherwise the function will deal with a copy of the value of the original object used as an argument expression and changing the copy of the value will not influence on the value of the original object.
In C passing by reference means passing an object indirectly through a pointer to it.
Thus dereferencing the pointer the function will have a direct access to the original object and can change it.
In this code snippet
char *buf = NULL;
size_t buf_size = 0;
ssize_t bytes_read = getline(&buf, &buf_size, stdin);
you want that the pointer buf after calling the function getline would point to a string read in the function. So you need to pass it to the function by reference the same way as you are passing another variable buf_size the value of which is also changed within the function and the caller of the function needs to know the result value of the variable.
If you will write
char **buf = NULL;
size_t buf_size = 0;
ssize_t bytes_read = getline(buf, &buf_size, stdin);
then the function within itself will try to dereference the null pointer buf that results in undefined behavior because it thinks that the so-called "double pointer" points to an object of the type char * that the function needs to change.
To make it more clear consider the following demonstration programs.
#include <stdio.h>
void f( char *s )
{
s = "World!";
}
int main( void )
{
char *s = "Hello";
printf( "Before calling f s = %s\n", s );
f( s );
printf( "After calling f s = %s\n", s );
}
The program output is
Before calling f s = Hello
After calling f s = Hello
The pointer s passed to the function be value. That is the function deals with a copy of the value of the pointer. Changing the copy does not influence on the original value of the pointer s.
Now consider the next program
#include <stdio.h>
void f( char **s )
{
*s = "World!";
}
int main( void )
{
char *s = "Hello";
printf( "Before calling f s = %s\n", s );
f( &s );
printf( "After calling f s = %s\n", s );
}
The program output is
Before calling f s = Hello
After calling f s = World!
That is as the pointer s is passed to the function by reference the function can change the original pointer s by dereferencing the pointer passed to the function that points to the original pointer s.
As for this declaration
char **name = "John Doe";
then the compiler should issue a message that declaration is wrong. The string literal used as an initializer is implicitly converted tp pointer to its first element of the type char *. But the initialized variable has the type char ** and there is no implicit conversion between these pointer types.
Also the conversion specifier %s expects an argument of the type char * instead of the type char **.
So you have to write
char *name = "John Doe";
Or as you may not change a string literal then it will be better to write the declaration like
const char *name = "John Doe";
In the char *buf case, getline will go to the memory location of the pointer buf and change that address.
In case of char **buf = NULL;, getline will go the memory location "null" and try to change that address, which is nonsense. You essentially lie to getline and tell it that you stored a pointer for it at memory location "null".
As for char **name = "John Doe"; it is a constraint violation of C's assignment rules, anything can happen since the code isn't valid C. Including "seems to work fine all the way until the mysterious crash some years later in live production code". You might want to take the skunk out of that online compiler by for example applying What compiler options are recommended for beginners learning C?
A double pointer has to reference a valid pointer to work (as that pointer will store the reference to the newly allocated memory.
int main(int ac, char **av)
{
printf("Write something: \n");
char *realBuf = NULL
char **buf = &realBuf;
size_t buf_size = 0;
ssize_t bytes_read = getline(buf, &buf_size, stdin);
if (bytes_read != -1)
write(STDOUT_FILENO, *buf, buf_size);
else
printf("An error occured\n");
free(*buf);
return (0);
}
There are no “double pointers” in C, so you cannot use them.
But for any type T, you can create a type “pointer to T”. And that’s the case if T is a pointer type as well. That’s a pointer to a pointer. Not a “double pointer”. If you see char** as a “double pointer” you will forever be confused.

Accessing char attribute of a struct

in my code I have a function that can initialize new instance of a struct, which has a char attribute, and the same function returns a pointer to an instance.
But when I try to read the char attribute from different scopes, I get also different characters.
Below you can find my code and also the results.
Thanks in advance!
Main function
Here the character is printed correctly.
int main(int argc, char const *argv[]) {
char line[] = "2-11 f: fjdfffmffffrff";
char *pnt = line;
Entry *entry = getEntry(&pnt);
printf("(main) min %d\n", entry->min);
printf("(main) max %d\n", entry->max);
printf("(main) character %c\n", entry->character); <-----
printf("(main) password %s\n", entry->password);
printEntry(entry);
return 0;
}
Function
While here the printed character is some random char.
void printEntry(Entry * entry){
printf("(function) min %d\n", entry->min);
printf("(function) max %d\n", entry->max);
printf("(function) character %c\n", entry->character); <--
printf("(function) password %s\n", entry->password);
}
STDOUT
Here are the results.
(main) min 2
(main) max 11
(main) character f
(main) password fjdfffmffffrff
(function) min 2
(function) max 11
(function) character L
(function) password fjdfffmffffrff
Edit
Entry struct
typedef struct Entry {
int min, max;
char character;
char *password;
} Entry;
char **separateBySpace(char **stringPtr) {
char **ptrArray = (char **) malloc(ARR_PTR_LEN * sizeof(char *));
char delim[] = " ";
char *ptr = strtok(*stringPtr, delim);
ptrArray[0] = ptr;
int x = 1;
while (ptr != NULL) {
if (x >= ARR_PTR_LEN) {
break;
}
ptr = strtok(NULL, delim);
ptrArray[x] = ptr;
x++;
}
return ptrArray;
}
Entry *getEntry(char **stringPtr) {
char **pntArray = separateBySpace(stringPtr);
char *rules = pntArray[0];
char *character = pntArray[1];
char *password = pntArray[2];
int *array = getRange(rules);
Entry entry = {.min = *(array), .max= *(array + 1), .character = *(character), .password= password};
Entry *pntEntry = malloc(sizeof(struct Entry));
pntEntry = &entry;
return pntEntry;
}
Function getEntry returns the address of a non-static local variable. Using this address in main is undefined behavior. Probably the call to printEntry partially overwrites the data, that's why you see different output.
You try to dynamically allocate memory for the returned data with
Entry *pntEntry = malloc(sizeof(struct Entry));
but you throw away the address to this memory and assign the address of your local variable with
pntEntry = &entry;
You probably want to copy the structure instead of the pointer. This would be
*pntEntry = entry;
Not related to your problem:
Your program should free all allocated memory when it is no longer used.
With the code shown in the question it is not necessary to pass the address of the pointer to the input string to getEntry and separateBySpace as a type char** because you don't want to modify the pointer. Passing a char* would be sufficient.
In separateBySpace you return an array of pointers that point to characters of the input string which gets modified by strtok. Later in getEntry you assign the pointer password to a pointer in your Entry structure. This means you should not change the string variable that was passed as an argument to getEntry, otherwise the password´ string referenced in the returned Entry` structure will change.
Edit (to answer a comment):
I think in getEntry you can free the pointer array allocated in separateBySpace because all values have been used or copied to the Entry structure.
At the end of the program you should free the memory pointed to by entry that was allocated in getEntry.
You must not free the memory password because this points to a character in your local variable line. Freeing entry->password before freeing entry would be necessary if you would allocate memory for a copy of the password, for example using strdup. This would also fix the possible problem that entry->password points to an element of line.

Allocating memory to a struct member pointer in C

I have a structure with a member that I need to pass to a function by reference. In that function, I'd like to allocate memory & assign a value. I'm having issues somewhere along the line - it seems that after the code returns from allocateMemory, the memory that I had allocated & the values that I assigned go out of scope (this may not be exactly what is happening, but it appears to be the case).
#include <stdio.h>
#include <stdlib.h>
typedef struct myStruct_t
{
char *myString;
} myStruct;
void allocateMemory(void *str);
int main(void) {
myStruct tmp = {
.myString = NULL
};
myStruct *p = &tmp;
allocateMemory(p->myString);
//allocateMemory(&(p->myString)); //also tried this
printf("%s", p->myString);
return 0;
}
void allocateMemory(void *str)
{
str = malloc(8);
((char *)str)[0] = 'a';
((char *)str)[1] = 0;
}
If I print the value of str inside of allocateMemory, the 'a' is successfully printed, but if I attempt to print p->myString in main, my string is empty.
Can anyone tell me what I'm doing wrong?
You need to pass address of the structure member and then you can change (aka allocate memory) to it. In your version of the function, you are not taking a pointer not reference of a pointer, so you can change the content of memory referenced by the pointer but not the pointer itself.
So change your function to
void allocateMemory(char **ret_str)
{
char *str = malloc(8);
str[0] = 'a';
str[1] = 0;
*ret_str = str;
}
And then call it as
allocateMemory(&p->myString)
An alternative way of writing the same function Rohan did, eliminating the need to define any new variables:
void allocateMemory(char **str, size_t size) {
*str = malloc(size);
(*str)[0] = 'a';
(*str)[1] = '\0';
}
Note that I pass a size parameter to justify using malloc() in the first place.

Assigning returned cstring to variable

I'm writing a function that reverses a cstring not in place but returns the reversed cstring. What exactly should the return type be?
#include <stdio.h>
#include <string.h>
const char* reverStr(const char *str)
{
char revStr[strlen(str)];
int i;
for(i = strlen(str)-1; i >= 0; i--)
revStr[strlen(str)-1-i] = str[i];
printf("returned value should be %s\n", revStr);
return revStr;
}
int main()
{
char aStr[] = "hello";
char aStr2[] = "goodbye";
printf("%s %s", aStr, aStr2);
char* tmp = reverStr(aStr);//tmp now has garbage
printf("\n%s", tmp);
printf(" %s", aStr);
return 0;
}
Gives
warning: function returns address of local variable [enabled by default]|
warning: initialization discards 'const' qualifier from pointer target type [enabled by default]|
I tried changing char* tmp to char tmp[] but it wouldn't compile. It confuses me when I should use an array and when I should use a pointer.
revStr is an array and ceases to exist after reverStr function exits. For more please read:
Where is the memory allocated when I create this array? (C)
const char* reverStr(const char *str)
{
char revStr[strlen(str)];
return revStr; /* Problem - revStr is a local variable trying to access this address from another function will be erroneous*/
}
const char* reverStr(const char *str)
{
const char * revStr = str;
return revStr; //ok
}
A modifiable l-value cannot have an array type. An l-value is an expression which can come on the left side of an assignment. You use an array when you want to declare lots of variables of the same type and you can index it easily since its layout will be in a sense contiguous.
You use pointers when you want to keep changing the values of the address where you variable points to.
You can do this:
char * p = "test";
p = "new";
But you cannot do this:
char p[] = "test";
char *p1 ="test1";
p = p1; //error
Because their (arrays and pointers) types are not the same and the array p is a non-modifiable l-value.
Here is your fixed code. I tried to make less modifications.
char revStr[strlen(str)]; allocates a local variable(an array) and when you are out of the scope of the reverStr function, its memory is released, which will lead any further usage of its pointer to be UB(segfault in most cases).
A correct way is to allocate the string on the heap and return its pointer like this
char* x = (char*)malloc(strlen(str));
...
return x;
This requires user to be responsible to free the memory. Or you could pass another parameter to your function for the result string.
I think you should use malloc to allocate a new string.
const char* reverStr(const char *str)
{
char *revStr;//using pointer
int i;
revStr = (char*)malloc(strlen(str));//dynamic allocation
for(i = strlen(str)-1; i >= 0; i--)
revStr[strlen(str)-1-i] = str[i];
printf("returned value should be %s\n", revStr);
return revStr;
}
An array is a pointer point to the head of continuous memory.
for example:
int a[] = {1,2,3};
The address in memory maybe:
--1000
|1|
--1004
|2|
--1008
|3|
--1012
1000, 1004, and 1012 are the value of address in memory.
Thus, the value of array a should be 1000.
printf("%d",a);// Yes, you can do it and you may get the value of 1000.
Also, you can use the following code.
int a[] = {1,2,3};
int *b;
b= a;
printf("%d",b[1]);// you will get "2".
You can consider that pointer is a set and array is in the set.
Therefore, you can NOT do this;
int a[] = {1,2,3};
int c = 0;
int *b = &c;
a = b;//error

Populate C output parameter

This is a beginner question, but please bear with me. I'd like to pass in a char* to a function, and have it populated, with the contents of multiple existing strings. Here's what I have (and doesn't work)
int func(char *out) {
int i;
int x = 10;
int y = 10;
char array[x][y];
out = malloc(x * y + x);
memset(out, 0x00, strlen(out));
for (i=0; i<x; i++) {
strcat(out, array[i]);
strcat(out, "\n");
}
}
//main
char *result;
func(result);
A char* is just a pointer, passing it in doesnt let you pass a new one back out again. You need to pass a char** like so:
void get_name( char** ppname ){
char * pname = strdup("my name is fred");
*ppname = pname;
}
You then feed the function somewhere to put the pointer like so:
char * name;
get_name( &name );
printf( "got '%s'\n", name );
free( name );
It doesn't work because you never allocated memory for your result variable - it's just a pointer that points to nowhere.
char result[1000]; // change size as needed if you know the size ahead of time
func(result);
or
char *pResult = malloc ( 1000 ); // allocate dynamically
if ( pResult != NULL )
func ( pResult );
...
if ( pResult != NULL )
free ( pResult );
You should also pass in the size of your buffer so your func function can check and verify that there's enough space available for its output.
Both of these solutions assume that you allocate your buffer outside of func. If you want to allocate the output buffer inside func than - as suggested by Als - you need to pass a pointer-to-pointer. In that case, you should also return the size of the buffer so the caller knows how many bytes are available in the buffer.

Resources