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)
Related
I am doing an exercise where the task is to fix swap_pointer().
Two string should be swapped.
s1 = "I should print second.";
s2 = "I should print first.";
My work so far:
#include <stdio.h>
void swap_nums(int *, int *);
void swap_pointers(char *x, char *y);
int main(void) {
int a = 3, b = 4;
char *s1, *s2;
swap_nums(&a, &b);
printf("a is %d\n", a);
printf("b is %d\n", b);
s1 = "I should be printed second.";
s2 = "I should be printed first.";
/* swap_pointers(s1, s2); */
printf("s1 is %s\n", s1);
printf("s2 is %s\n", s2);
return 0;
}
void swap_nums(int *x, int *y) {
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
void swap_pointers(char *x, char *y) {
char tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
I think that not appending & to s1 and s2 before I pass them to the function for swap_pointers is the error?
If anyone can fix my issue here, please don't give the whole solution! I want to use what you give me as a tool to fix it by my own. If I really can't fix it by my own I will adress this later.
Ty in advance!
Let's at first consider this code snippet
int a = 3, b = 4;
swap_nums(&a, &b);
To swap the objects a and b you need to pass then to the function swap_nums by reference through pointers to them. Thus within the function dereferencing the pointers we can get a direct access to original objects and change their values.
void swap_nums(int *x, int *y) {
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
The same we need to do with the variables s1 and s2. That is we need to pass them to the function swap_pointers by reference through pointers to them.
So you need to write
swap_ponters( &s1, &s2 );
and the function will be declared and defined like
void swap_ponters(char **x, char **y)
{
char *tmp = *x;
*x = *y;
*y = tmp;
}
In general if you have two objects like
T a;
T b;
where T is some type specifier then to change the objects in a function you need to pass them to the function by reference through pointers to them. So the declaration of the function swap will look like
void swap( T *a, T *b );
and the function will be called like
swap( &a, &b );
In your program a and b has the type int, that is T is an alias for the type int.
typedef int T;
T a = 3, b = 4;
so the function declaration will look like
void swap_nums( T *x, T *y );
For the variables s1 and s2 you can write
typedef char *T;
T s1, s2;
and again the function declaration will look like
void swap_pointers( T *x, T *y );
and the function will be called like
swap_pointers( &s1, &s2 );
As in this case T is an alias for the type char * then the function declaration can be rewritten like
void swap_pointers( char * *x, char * *y );
Your pass the pointers to the first characters of two null-terminated strings to the swap_pointers function.
Inside the function, when you use e.g. *x it's the same as x[0].
So you're swapping the first character of x with the first character of y.
If you want to switch pointers, you need to emulate pass-by-reference like you do with swap_nums, and pass pointers to the pointers, i.e. char **. And use the pointer-to operator & in the call.
So it should be
void swap_ponters(char **x, char **y);
and
swap_pointers(&s1, &s2);
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
Hello I have the following functions defined:
head();
traverse(struct *);
I'm concerned that when iterating through the list it is being modified.
void tail()
{
n3.next = (struct entry*) 0xff;
}
void traverse(struct entry *listPt)
{
while(listPt != (struct entry *) 0xff)
{
printf("%i\n", listPt->value);
listPt = listPt->next;
}
}
Should I use a different algorithm to iterate the list? Is it more beneficial to copy the list?
Is the following expression from the while loop overwritten existing (values) memory?
listPt = listPt->next;
The statement overrides only local variable listPt declared as a function parameter
struct entry *listPt
It does not modify the list itself.
Function parameters are its local variables. The function deals with copies of its arguments. Any changing of a parameter does not influence on the corresponding argument.
Consider
#include <stdio.h>
void func( int *p )
{
int y = 20;
p = &y;
printf( "%d\n", *p ); // prints 20
}
int main( void )
{
int x = 10;
int *px = &x;
printf( "%d\n", *px ); // prints 10;
func( px );
printf( "%d\n", *px ); // prints 10;
}
No this algorithm is ok, you wont modify the list.
If you want to modify you have to set the function header like this void traverse(struct entry * & listPt)
I have written code to swap strings, but I am not able to swap. What is the problem and how can I solve it by using a function, swap?
#include <stdio.h>
void swap( char*,char*);
int main()
{
char *ptr[2] = {"hello", "morning"};
swap(ptr[0], ptr[1]);
printf("%s %s", ptr[0], ptr[1]);
return 0;
}
void swap(char *t1, char*t2)
{
char *t;
t = t1;
t1 = t2;
t2 = t;
}
I also tried to pass (&ptr[0], &ptr[1]), but here it shows a segmentation fault. Also I made a char, *p1 = ptr[0], char *p1 = ptr[1], and then passes &p1, and &p2 to swap, but still I get a segmentation fault.
C function arguments are pass-by-value. You're passing the value of addresses to your swap function, and expecting those values, the addresses, to change. But only the copies of the addresses in your swap function change.
To change the actual passed-in addressed, you'll need an aditional level of reference:
void swap(char **t1, char **t2)
{
char *t;
t = *t1;
*t1= *t2;
*t2 = t;
}
And call this swap like so: swap(&ptr[0], &ptr[1]);
You need to pass in pointers to the pointers of the char arrays in order to switch them. By doing that you can swap the values of those pointers instead. (Which are the actual arrays.)
#include<stdio.h>
void swap( char**,char**);
int main()
{
char *ptr[2] = {"hello","mornig"};
swap(&ptr[0], &ptr[1]);
printf("%s %s",ptr[0], ptr[1]);
return 0;
}
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}
You need to pass pointers to your strings to swap them (char**). Otherwise the changes you do will be local to the swap function.
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}
int main()
{
char *ptr[2] = {"hello","mornig"};
swap(&ptr[0], &ptr[1]);
printf("%s %s",ptr[0],ptr[1]);
return 0;
}
char *ptr[2] = {"hello","mornig"}; - This statement means you are allocating an array of size 2 which is going to store a address of two strings(ie char *). Now the two strings you are giving will be in text segment which is a read only data. If we tries to modify it, which will leads to crash(sgmentation fault).
So if you call swap(&ptr[0], &ptr[1]) leads to a crash. because you are trying to write the charcter m in the first read only string h. Write is not possible to the string which is in text segment.
If you want to simply swap a string you can call the function as swap(&ptr[0], &ptr[1]), which is equivalent to swap((ptr + 0),(ptr + 1));.
And change the swap function as below
void swap( char **t1,char **t2)
{
char *t;
t = *t1;
*t1 = *t2;
*t2 =t;
}
Here we are just swapping the address of the string stored in the array pointer ptr.
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.