I made a code to swap two strings:
void swap (char *a, char *b)
{
char *t = a;
a = b;
b = t;
}
int main()
{
char * strings[2];
strings [0] = "luck!";
strings [1] = "good ";
swap (strings[0], strings[1]);
printf( "%s %s\n",strings[0], strings[1]);
return 0;
}
And it fails. What i have trouble understanding is when i call swap() i pass two pointers. Both pointers point to the first character of their assigned arrays. I then created a temporary pointer inside the function and perform basic switch. What is flawed here? I really want to understand why this approach is wrong?
You are switching the parameters of the function, which are local to the function scope. When your function is executed, the parameters (a, of type char*, and b, of type char*) are passed by value, put on the stack, and the function is executed. The parameters are modified and then popped of the stack without effect.
To make a difference, you need to pass references to the parameters:
void swap (char **a, char **b)
{
char *t = *a;
*a = *b;
*b = t;
}
and then call with:
swap (&strings[0], &strings[1]);
You now pass pointers to individual array elements in strings, which is in main's stack segment and thereby persists past the context of swap.
You pass a copy to the pointers to the function and thus you exchange the copies. In C you will have to pass a pointer to the pointers to actually swap them.
If you want to swap values through pointers, you need to use assigments of the form
*a = *b;
If you would do that in your code, it would swap the first characters of the strings. To swap the pointers, you need to have paraemters of type char**, and pass &strings[0].
Just to give you example, about what other answers suggesting ...
Update your swap function to
void swap (char **a, char **b)
{
char *t = *a;
*a = *b;
*b = t;
}
And then call it in main as
swap(&strings[0], &strings[1]);
However, you may want to update assignment of strings as string like "luck!" is constant and you cannot update its individual characters.
strings [0] = strdup("luck!");
strings [1] = strdup("good ");
Related
When I was introduced to pointers, I was told that they are useful because they let us modify certain variables fed into functions that wouldn't normally be modifiable. For example:
void copy(int *p, int *s);
int main(){
int a = 4, b = 10, *p = &a, *s = &b;
copy(p, s);
}
void copy(int *p, int *s){
*s = *p;
*p = 0;
}
So at the end of this, "b" is equal to "a", and "a" is equal to 0, even though "a" and "b" wouldn't normally be modifiable.
When talking about lists and, specifically, adding an element to a list, I can use a function like this:
struct list{
int n;
struct list *next;
}
struct list *first = NULL;
int main(){
int n = 3;
first = add_to_list(first, n);
}
struct list *add_to_list(struct list *first, int n){
struct list *new_node;
new_node = malloc(sizeof(struct list));
if(new_node == NULL) exit(EXIT_FAILURE);
new_node->value = n;
new_node->next = first;
return new_node;
}
What concerns me specifically is why the function can't simply return a type void, and instead of writing "return new_node", I can't simply write "first = new_node". Because first is a pointer, if I modify it anywhere in my program the original pointer should be modified too, just like it happened in the first example I made, right?
Also, bit of an unrelated question, but if I've got a function like this:
void first_to_n(int a[], int n){
a[0] = n;
}
The first element of the original vector a, which lets say is declared in main, gets also modified, right? Because vectors can be considered as pointers
Lets say we have something like the following code
void funcA(int x)
{
x = 0;
}
void funcB(int *y)
{
y = NULL;
}
int main(void)
{
int a = 10;
int *b = &a;
funcA(a);
funcB(b);
}
What happens when funcA is called is that the value of a is copied into the separate variable x inside the function. When the call is being made there are two copies of the value 10 stored in to different places. When the assignment x = 0 is done inside the function, only the local variable x is modified.
For funcB just the same happens. The value of the variable b is copied into the separate variable y in the function. That means there are two separate and distinct variable pointing to the same location. But once the assignment y = NULL is done, that's no longer true. The variable y is no longer pointing to the same location, but in the main function b is unmodifed since only a copy of the value was passed to the function.
If we now take a slightly different example
void func(int *x, int **y)
{
*y = x;
}
int main(void)
{
int a = 10;
int b = 20;
int *c = &a; // Make c point to the variable a
func(&b, &c);
}
After the function is called, then c does no longer point to a, it points to b. That's because for the second argument the value we pass is &c which is a pointer to the variable c. Inside the function we can then use the dereference operator to access what y is pointing to (which will be the variable c in the main function).
When I was introduced to pointers, I was told that they are useful because they let us modify certain variables fed into functions that wouldn't normally be modifiable.
Among other things, like creating non-trivial data structures and to avoid copies.
Because first is a pointer, if I modify it anywhere in my program the original pointer should be modified too, just like it happened in the first example I made, right?
first (the parameter) is a copy of first (the global). Therefore, first = new_node would only modify your pointer, not the global one.
This is more clear in your first example:
void copy(int *p, int *s){
*s = *p;
*p = 0;
}
If you were doing p = 0;, for instance, you would only modify the pointer, not the value pointed to.
The first element of the original vector a, which lets say is declared in main, gets also modified, right? Because vectors can be considered as pointers
That is not a "vector" (array), it is a pointer even if it looks like an array. It is a big gotcha of C.
But, indeed, a[0] = 0; is modifying the first value (in main) pointed by the parameter.
What concerns me specifically is why the function can't simply return
a type void, and instead of writing "return new_node", I can't simply
write "first = new_node".
As the other answers explain, you can't due to first being a 'copy' of the pointer outside the function. If however you were to instead change the function such that you passed a 'pointer to the pointer' rather that just the 'pointer', then you could change the external value, which is what's going on the in the 'copy' function.
This uses a pointer to a literal string.
The pointer is pass to modifypointer() where it is modified to point to another literal string. The new literal string is printed in the function, but main() still prints the original.
The pointer is passed as a pointer to itself in modifypointertopointer() where it is dereferenced to point to another literal string. Now the function prints the new literal string and main() also prints the new literal string.
In your last example, first = new_node; could be used except the function declares a shadow variable first and the global first is no longer in the scope of the function.
#include <stdio.h>
void modifypointer( char *mod) {
mod = "modify pointer";
printf ( "%s\n", mod);
}
void modifypointertopointer( char **ptrmod) {
*ptrmod = "modify pointer to pointer";
printf ( "%s\n", *ptrmod);
}
int main( void) {
char *text = "original";
printf ( "%s\n", text);
modifypointer ( text);
printf ( "%s\n", text);
modifypointertopointer ( &text);
printf ( "%s\n", text);
return 0;
}
I'm trying to understand the mistake in the following code. The code is supposed to switch between two arrays.
What I saw is that it switches only the first 4 bytes. Is the following correct?
Passing &num1 or num1 is the same (both pass the address of the first element in the array).
The (char**) casting is wrong. That's because when you pass and array you pass the address it's laid in. So you actually pass here a void*.
How can I actually switch between these two arrays only by pointers? Is thatpossible?
I know it is possible if from the beginning I had defined char **num1 and char **num2. But I want it to stay with the array notation!
#include <stdio.h>
void fastSwap (char **i, char **d)
{
char *t = *d;
*d = *i;
*i = t;
}
int main ()
{
char num1[] = "hello";
char num2[] = "class";
fastSwap ((char**)&num1,(char**)&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
Passing &num1 or num1 is the same (both pass the address of the first element in the array). Am I correct?
No. The first one is a pointer to the array itself (of type char (*)[6]), whereas in the second case, you have a pointer to the first element (of type char *; an array decays into a pointer to its first element when passed to a function).
The (char*) casting is wrong
Indeed, you are casting a char (*)[6] to a char **.
So you actualy pass here a void (Am i correct?).
No. Non sequitur. I don't see how the void type is relevant here. You have pointers, arrays, and eventually pointers to arrays.
Arrays are not pointers. Your code is trying to swap arrays, which does not make sense, since assignment to arrays is not permitted. What you probably want is
I. either get pointers to the first character of each string, and then swap the pointers themselves, like this:
void swap_pointers(const char **a, const char **b)
{
const char *tmp = *b;
*b = *a;
*a = tmp;
}
const char *p1 = "hello";
const char *p2 = "world";
swap_pointers(&p1, &p2);
II. Or use actual arrays, and you swap their contents:
void swap_contents(char *a, char *b, size_t n)
{
for (size_t i = 0; i < n; i++) {
char tmp = a[i];
a[i] = b[i];
b[i] = tmp;
}
}
char a1[] = "hello";
char a2[] = "world";
swap_contents(a1, a2, strlen(a1));
Also, you may want to read this.
1. Passing &num1 or num1 is the same (both pass the address of the first element in the array)
Not true, &num1 gives you a pointer to a pointer that points to the entire character string "hello" (char*[6]) while num1 is just a pointer to the character block "hello" (char[6]).
2. The (char*) casting is wrong. That's because When you pass and array you pass the address it's laid in. So you actualy pass here a void (Am i correct?).
It is still not a void, it's just a pointer to a character pointer. If it were void, then it would be perfectly valid to do something like void** myVoid = &num1. This will cause a syntax error unless you explicitly typecast your char** to a void** before you assign it.
The problem is your explicit type casting &num1 as a char** which is not correct, it is a char*[6]. But of course, you can't declare a variable as a char*[6] so it can't be used in this way. To fix it you need to declare your num1 and num2 as:
char* num1 = "hello";
char* num2 = "class";
instead and keep everything else the same. In fact, with this change there is no need to typecast your &num1 as a char** because it already is that.
void swap(char *a,char *b){
char t;
t = *a;
*a = *b;
*b = t;
}
int main(void){
char a = '1';
char b = '2';
swap(&a,&b);
printf("The value is %c and %c respectively\n",a,b);
return 0;
}
in the above code, there's a spot that confuse me
I think if a is a pointer, and *a is the value it points to
int *ptr, a = 1;
ptr = &a;
printf("The value of *ptr should be a: %d\n",*ptr);
printf("The value of *a should be an hex address: %p\n",ptr);
so in the swap(char *a, char *b) function,it takes the value not pointer( *a not a),
swap(&a, &b)
but it actually pass the pointer value to it as the parameter, and the code works. Anybody can explain it to me?(I think for swap(char *a){...} part, the declaration doesn't mean it require *a to pass in, it means declare a pointer value a, not the value a points to as *ain elsewhere means).
* is confusing because it means two different, but closely related, things. In a variable declaration, * means "pointer". In an expression, * means "dereference the pointer".
It's intended to be a helpful mnemonic: if you have char *a in your code it means that *a is a char.
Your function
swap(char *a, char *b)
takes two parameters, both of which are of type char *. Quite literally that means they point to a character somewhere in memory.
When you dereference the pointer
t = *a;
You are saying "grab whatever a is pointing to and put it in t.
Perhaps the confusion is from the fact that * means two related but different things. In the case char *, it's defining a type, specifically one that points to a character somewhere in memory. In the case *a, the * means "look at the character being pointed to by a and let me know what it is".
In main:
a is a char
&a is a pointer to the char a.
In swap:
a is a pointer to a char
*a is the char pointed to by a.
You passed a pointer to a pointer, and it worked beautifully. Try drawing a picture with boxes and errors. Clears things up every time. Just remember your code has two as and two bs.
Yes, the asterisk * has multiple meanings related to pointers:
It be used in a declaration to introduce a variable that contains an address - a pointer:
int *ptr = NULL;
Similarly in an argument list, such as void swap(char *, char *).
It can also be used to dereference an existing pointer, or get the value pointed to, as within the function swap:
t = *a;
This generally causes a good deal of confusion for students who are new to C, but it's actually quite simple.
In this our aim is to swap the value
when you write char a='1'; i.e you are putting '1' at address 662442(suppose &a=662442).
char b='2'; i.e you are putting '2' at address 662342(suppose &b=662342).
now consider swapping a and b,here our aim is to change value at 662442(&a) to value at 662342(&b) and value at 662342(&b) to value at 662442(&a).
now for swapping we take a temporary variable char temp and will do the following
temp=*a; i.e assigning value at address 662442(&a) to temp.
*a = *b; i.e assigning value at address 662342(&b) to value at address 662442(&a).
now we will put previous value of a (i.e value kept in variable temp) at address 662342(&b)
*b = temp; i.e assigning temp to address 662442(&a)
I am trying to write a program that will mutliply two numbers, but output the result in binary, showing the calculation (i.e. shifting the rows). I'm storing the binary numbers as an array of 32 characters, and each element is either 1 or 0.
I have a function that will convert decimal to binary character array, but then my array only exists within the function, but I need to use the array within another function and also within main. I was thinking it might be possible to use pointers to change the value of the array in main from within my converter function, so then the array will exist in main and can be used in other functions. Is this possible?
I've declared two pointers to character arrays:
char (*binOne)[32];
char (*binTwo)[32];
if I pass the pointer as a parameter to the function, can I still access each element? Sorry if I'm not making much sense here.
In C, most of the time array behaves like pointer to its first element, so what you probably want to do is:
void foo(char* arr){
//some stuff, for example change 21-th element of array to be x
arr[20] = 'x';
}
int main(){
char binOne[32];
char binTwo[32];
// change array binOne
binOne[20] = 'a';
foo(binOne);
// now binOne[20] = 'x'
foo(binTwo);
// now binTwo[20] = 'x'
}
A continuation of what I added as a comment:
In C, if you want to modify/return an array, you'll do that by passing a pointer to it as an argument. For example:
int toBinary(char *buff, int num) { /* convert the int, return 1 on success */ }
...
char buff[32];
toBinary(buff, 9001);
In C, an array's name is it's address, it's the address of the first element:
buff == &buff == &buff[0]
Yes, this is possible. But you only need a pointer to the array not an array of pointers.
You need to prototype like
e.g.
void int_to_arr(int n, char *arr);
void arr_to_int(int *n, char *arr);
in main(){
char *binarr = calloc(32, sizeof(char));
int n = 42;
int_to_arr(n, binarr);
}
void int_to_arr(int n, char *arr)
{
//do you conversion
//access array with
// arr[i]
}
void arr_to_int(int *n, char *arr)
{
//do you conversion
//access array with
// *n = result;
}
Suppose I have an array of pointers to char in C:
char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
And I wish to sort this array using qsort:
qsort(data, 5, sizeof(char *), compare_function);
I am unable to come up with the compare function. For some reason this doesn't work:
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = (const char *)name1;
const char *name2_ = (const char *)name2;
return strcmp(name1_, name2_);
}
I did a lot of searching and found that I had to use ** inside of qsort:
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = *(const char **)name1;
const char *name2_ = *(const char **)name2;
return strcmp(name1_, name2_);
}
And this works.
Can anyone explain the use of *(const char **)name1 in this function? I don't understand it at all. Why the double pointer? Why didn't my original function work?
Thanks, Boda Cydo.
If it helps keep things straight in your head, the type that you should cast the pointers to in your comparator is the same as the original type of the data pointer you pass into qsort (that the qsort docs call base). But for qsort to be generic, it just handles everything as void*, regardless of what it "really" is.
So, if you're sorting an array of ints, then you will pass in an int* (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to int*, and dereference to get the int values that you actually compare.
Now replace int with char*:
if you're sorting an array of char*, then you will pass in a char** (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to char**, and dereference to get the char* values you actually compare.
In your example, because you're using an array, the char** that you pass in is the result of the array of char* "decaying" to a pointer to its first element. Since the first element is a char*, a pointer to it is a char**.
Imagine your data was double data[5] .
Your compare method would receive pointers (double*, passed as void*) to the elements (double).
Now replace double with char* again.
qsort is general enough to sort arrays consisting of other things than pointers. That's why the size parameter is there. It cannot pass the array elements to the comparison function directly, as it does not know at compile time how large they are. Therefore it passes pointers. In your case you get pointers to char *, char **.
The comparison function takes pointers to the type of object that's in the array you want to sort. Since the array contains char *, your comparison function takes pointers to char *, aka char **.
Maybe it is easier to give you an code example from me. I am trying to sort an array of TreeNodes and the first few lines of my comparator looks like:
int compareTreeNode(const void* tt1, const void* tt2) {
const TreeNode *t1, *t2;
t1=*(const TreeNode**)tt1;
t2=*(const TreeNode**)tt2;
After that you do your comparison using t1 and t2.
from man qsort:
The contents of the array are sorted in ascending
order according to a comparison function pointed to by
compar, which is called with two arguments that **point**
to the objects being compared.
So it sounds like the comparison function gets pointers to the array elements. Now a pointer to a char * is a char **
(i.e. a pointer to a pointer to a character).
char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
is a statement asking the compiler for an array of size 5 of character pointers. You have initialized those pointers to string literals, but to the compiler, it's still an array of five pointers.
When you pass that array into qsort, the array of pointers decays into a pointer pointing to the first element, in accordance with C array parameter passing rules.
Therefore you must process one level of indirection before you can get to the actual character arrays containing the constants.
#bodacydo here is a program that may explain what other programmers are trying to convey but this would be in context of "integers"
#include <stdio.h>
int main()
{
int i , j;
int *x[2] = {&i, &j};
i = 10; j = 20;
printf("in main() address of i = %p, address of j = %p \r\n", &i, &j);
fun(x);
fun(x + 1);
return 0;
}
void fun(int **ptr)
{
printf("value(it would be an address) of decayed element received = %p, double dereferenced value is %d \r\n",*ptr, **ptr);
printf("the decayed value can also be printed as *(int **)ptr = %p \r\n", *(int **)ptr );
}
qsort() passes a pointer to the user-defined comparison function and as you have a char * (pointer to char array) hence your comparison function should dereference from pointer to pointer hence char **.