I want to use a local pointer to point to a global string. The pointer is a local pointer and the string is global. When I run this code passing the local pointer to the function "myfun" the pointer is not changed, i.e., its pointing address does not change. The values printed are "NULL".
Can someone tell me why this does not work on gcc?
#include <stdio.h>
char *str[] = { "String #1", "Another string" };
void myfun( void * p, int i )
{
p = ( void * ) &str[ i ][ 0 ];
}
int main( void )
{
void * ptr1, * ptr2;
myfun( ptr1, 0 );
myfun( ptr2, 1 );
printf( "%s\n%s\n", ptr1, ptr2 );
}
You are passing a pointer, by value, to myfun. The value you assign to p in myfun is therefore not returned to the caller. You need to pass a pointer to the pointer:
void myfun( void ** p, int i )
{
*p = ( void * ) &str[ i ][ 0 ];
}
And call it like this:
myfun( &ptr1, 0 );
In fact you can write myfun like this:
void myfun( void ** p, int i )
{
*p = str[i];
}
And in fact it would be simplest just to return the void* as the functions return value:
void *myfun( int i )
{
return str[i];
}
Fundamentally, your question isn't any different from -
void func(int i)
{
i = 2;
}
int main()
{
int i = 0;
printf("i = %d\n", i);
func(i);
printf("i = %d\n", i); /* Wonder why it doesn't output i = 2? */
}
In your code, you pass ptr1 (and ptr2) arguments by value, change the value of the parameter p that you receive, and expect this change to be reflected on the argument that you passed. That, that ptr1 and ptr2 are pointers doesn't change the fact that you are still passing by value.
Also, IANAL (i.e., I hope a language lawyer corrects me if I am wrong), but I think you are potentially headed for trouble by sending pointer to void variables as arguments to printf.
Related
I need to create a swap function that takes 2 addresses as input and swaps them regardless what type they point to. Here's my swap function:
void swap(void* x,void* y){
void* temp=x;
x=y;
y=temp;
}
When I use it with integers it works fine and swaps them properly, but using strings the addresses seems to swap inside the function but when I try to call them from outside the function I notice they didn't change at all.
Here's my full code and the resulting output.
printf("before %s %s\n",(char*)array[i],(char*)array[j] );
swap(array[i], array[j]);
printf("after %s %s\n",(char*)array[i],(char*)array[j] );
I casted everything to string to understand what was wrong with them
void swap(void* x,void* y){
printf(" after IN %s %s\n",(char*)x,(char*)y );
void* temp=x;
x=y;
y=temp;
printf(" after IN %s %s\n",(char*)x,(char*)y );
}
OUTPUT
before fannullone falafel
after IN fannullone falafel
after IN falafel fannullone
after fannullone falafel
To swap two objects in a function you need to pass them to the function by reference.
In C passing by reference means passing objects indirectly through pointers to them. So dereferencing the pointers the function gets a direct access to the original objects and can change them.
So for objects of the type void * the function parameters will have the type void **. The function will look like
void swap( void **x, void **y )
{
void *temp = *x;
*x = *y;
*y = temp;
}
Here is a demonstration program.
#include <stdio.h>
void swap( void **x, void **y )
{
void *temp = *x;
*x = *y;
*y = temp;
}
int main( void )
{
void *s1 = "Hello";
void *s2 = "World";
printf( "s1 = %s, s2 = %s\n", ( char * )s1, ( char * )s2 );
swap( &s1, &s2 );
printf( "s1 = %s, s2 = %s\n", ( char * )s1, ( char * )s2 );
}
The program output is
s1 = Hello, s2 = World
s1 = World, s2 = Hello
It cannot be done with a function because there is no generic pointer to pointer in C. For example the type void** is not compatible with char**. Technically, those pointers could have different representation what would disallow dereferencing after casting or using memcpy().
Therefore, it is better to use a macro:
#define SWAP(a, b) \
do { \
void *tmp = *(a); \
*(a) = *(b); \
*(b) = tmp; \
} while (0)
I am well aware that there are many similar questions, but have not yet find the one that solves this. So I will also thank anyone that could point me to the duplicate.
Say I have a function that takes a void pointer and modify the value inside:
int func(void *head)
{
if (head == NULL){
printf("is null\n");
/* do sth with the value */
}
else{
printf("not null\n");
/* do sth with the value */
}
return 1;
}
And I passed a NULL pointer by address into it:
void *setList = NULL;
func(&setList);
It would give me not null, which is not what I want. (if passing by value it works well)
What was I missing? How could I judge if it's a NULL pointer when passed by address?
Thanks.
In this declaration
void *setList = NULL;
you declared the variable setList that occupies a memory. So the address of the variable itself is not equal to NULL. It is the value of the variable that is stored in the allocated for the variable memory that is equal to NULL.
In this call
func(&setList);
the type of the argument expression is void **.
Within the function declared like
int func(void *head);
you have at first cast the pointer head to the type void **.
For example
void **p = ( void ** )head;
and then in the if statement you need to dereference the pointer p like
if ( *p == NULL )
//...
Here is a demonstrative program.
#include <stdio.h>
int func( void *head )
{
void **p = ( void ** )head;
if ( *p == NULL )
{
puts( "p is a null pointer" );
}
else
{
puts( "p is not a null pointer" );
}
return 1;
}
int main(void)
{
void *setList = NULL;
func( &setList );
int x = 10;
setList = &x;
func( &setList );
return 0;
}
Its output is
p is a null pointer
p is not a null pointer
As for your original code then a question arises why is not the function declared like
int func(void **head);
if you are going to pass a pointer to pointer?
void *setList = NULL;
you create the variable setlist having the type of pointer to void and initialize it to NULL.
func(&setList);
you pass the address of the variable setList not the value of it. The variable is the valid object and its address is by definition not NULL.
I am relatively new to programming, and im trying to understand some concepts with pointers. I got it for the most part, and i was looking in dinamic memory allocation, and i understood i need to create a pointer and the malloc function will return the first adress of the allocated space, which we put in the pointer created. That make a lot of sense because thats makes the dinamic vector just like a regular vector, right? Because a static vector also has the name of the vector a pointer to the first element. But why when i try to for example change the size of the vector with realloc in a function i understand i need to use a double pointer as a parameter. Something like this:
void function(int **vector){
*vector=(*int)realloc(*vector, sizeof(int)*n);
}
Can someone explain, thanks!
When a function declared as void function(int *vector) is called, it is passed only the value of an int *—just a pointer to the first element of a vector (an array). If this function is called with function(MyVector), then, inside the function, vector refers only to the copy of the value that is passed. It does not refer to MyVector, and changing vector will not change MyVector.
When a function declared as void function(int **vector) is called, it is passed the value of an int **—a pointer to a pointer to the first element of a vector. If this function is called with function(&MyVector), then, inside the function, vector refers to the copy of the pointer to the pointer. However, since it is a pointer to a pointer, then *vector refers to the pointer to the first element of the array. That is, *vector is not just a copy of the pointer, it is the actual pointer, the MyVector in the caller.
So, in the first function vector = realloc(…); does not change MyVector in the caller. In the second function, *vector = realloc(…); does change MyVector in the caller.
If you have a function like this
void f( T item );
where T is some type specifier and call it like
T object;
f( object );
then the function gets a copy of its argument. You can imagine this the following way
T object;
f( object );
//....
void f( /* T item */ )
{
T item = object;
// ...
}
So changes of the copy within the function dos not influence on the original object passed to the function as an argument.
To change the original object you have to pass it by reference. For example
void f( T *item )
{
*item = new_value;
//...
}
//...
T object;
f( &object );
If you have an object of the type int that you want to change within a function then just substitute the type specifier T for the type int and you will get.
void f( int *item )
{
*item = new_value;
//...
}
//...
int object;
f( &object );
If the object has the type int * then substitute T for int * and you will get
void f( int **item )
{
*item = new_value;
//...
}
//...
int *object;
f( &object );
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
void f( int *x )
{
*x = 20;
}
void g( int **p )
{
*p = malloc( sizeof( int ) );
**p = 30;
}
int main(void)
{
int x = 10;
printf( "x = %d\n", x );
f( &x );
printf( "x = %d\n", x );
int *px = &x;
printf( "*px = %d\n", *px );
g( &px );
printf( "*px = %d\n", *px );
free( px );
return 0;
}
Its output is
x = 10
x = 20
*px = 20
*px = 30
I need to do a simple thing, which I used to do many times in Java, but I'm stuck in C (pure C, not C++). The situation looks like this:
int *a;
void initArray( int *arr )
{
arr = malloc( sizeof( int ) * SIZE );
}
int main()
{
initArray( a );
// a is NULL here! what to do?!
return 0;
}
I have some "initializing" function, which SHOULD assign a given pointer to some allocated data (doesn't matter). How should I give a pointer to a function in order to this pointer will be modified, and then can be used further in the code (after that function call returns)?
You need to adjust the *a pointer, this means you need to pass a pointer to the *a. You do that like this:
int *a;
void initArray( int **arr )
{
*arr = malloc( sizeof( int ) * SIZE );
}
int main()
{
initArray( &a );
return 0;
}
You are assigning arr by-value inside initArray, so any change to the value of arr will be invisible to the outside world. You need to pass arr by pointer:
void initArray(int** arr) {
// perform null-check, etc.
*arr = malloc(SIZE*sizeof(int));
}
...
initArray(&a);
I know the c always pass by values, but if I have a pointer:
int i = 4;
int * p;
p = &i;
then I have a function, how to pass pointer p to it and change the value of variable i?
void changeValue(int *p)
{
}
how to pass the pointer and change the variable pointed by p?
This simple example shows how to pass a pointer (i.e. not a value) and recieve back through that pointer, the new value held by the integer. Note the reduced number of variables. i.e. there is no need necessarily to create a separate copy of int *p;. Nor is it necessary in this case to initialize p: p = &i; to the address of i.
int changeValue(int *);
int main(void)
{
int i=15;
changeValue(&i);
return 0;
}
int changeValue(int *p) //prototyped to accept int *
{
return *p = 3;
}
If you do want to create a pointer in the first place, and pass that pointer, then:
int changeValue(int *);
int main(void)
{
int i=15;
int *p;
p = &i;
*p; // *p == 15 at this point
//since p is already a pointer, just pass
//it as is
changeValue(p);
return 0;
}
int changeValue(int *q) //prototyped to accept int *
{
return *q = 3;
}
It is important to note that your statement: I know the c always pass by values is not correct. It is more common for functions to be written such that pointers are passed because often a pointer is smaller, and more efficient to pass around than the actual variable, especially when large arrays, or structs are used. Keep in mind though that passing &i (the address of i) works just as well as passing p if passing a pointer is called for.
Simply pass it by calling changeValue as
changeValue(p);
and change the value of variable pointed by it (i) by assigning a value to the *p in changeValue()
void changeValue(int *p)
{
*p = an int value;
}
void changeValue( int* ) ;
int main( void )
{
int i = 4; // Suppose i is stored at address 1000h
int * p;
p = &i; // Now p stores the address of i that is 1000h
changeValue(p); // Can also be written as changeValue(&i);
// Here you are passing the address of i to changeValue function
return 0 ;
}
void changeValue( int* p ) // Accept a parameter of type int*
{
*p = 100 ; // store the value 100 at address 1000h
return ;
}
int i = 4;
int * p = &i;
changeValue(p);
printf("%d",*p);
void changeValue(int *p)
{
*p = 5;
}
Full program - http://ideone.com/DCvhxE
If you dereference the pointer in changeValue and assign to it, it will alter the value of i in the calling frame.
e.g.:
void changeValue(int *p)
{
*p = 0;
}