string swapping works well with char ** but not with char * - c

In this program I have swapped the first 2 names
#include<stdio.h>
void swap(char **,char **);
main()
{
char *name[4]={"amol", "robin", "shanu" };
swap(&name[0],&name[2]);
printf("%s %s",name[0],name[2]);
}
void swap(char **x,char **y)
{
char *temp;
temp=*x;
*x=*y;
*y=temp;
}
This programs runs perfectly but when I use the function swap(char *,char *) it does not swap the address why? why I have to use pointer to pointer?

I assume you understand that to swap integers you would have function like swap(int *, int *)
Similarly, When you want to swap strings which is char *. You would need function like swap(char **, char **).
In such cases, you take their pointers and swap their content (otherwise values will not be swapped once function returns). For integer content, pointer is int * and in case of strings content is char * pointer to it is char **.

Pointers (like all values) are passed by value.
If you use swap(char * a,char * b) and write a = tmp; this changes only the local variable a and not the original variable in the caller.
This simpler example also doesn't work as intended for the same reason:
void change(int x) {
x = 0; // Only changes the local variable.
}
int main(void) {
int x = 0;
change(x); // This does not have any effect.
printf("%d", x); // 0 is printed
return 0;
}
http://ideone.com/u7Prp

char *name[4] is holding address of 3 string literals. If we want to swap, we have to pass the reference of the array where exactly the string literal's address is stored. That means we have to pass name+0 and name+2 or &name[0] and &name[2] to the swap function.
And also if you want to swap. you have to receive the address as char ** and then we have to change the address of the string literals in the array.
If you receive it as char * and if you tries to change like temp = x; x = y; y = temp, that will be local change to the function swap. It will not reflect on the array name.

Sounds like this is what you are looking for:
#include<stdio.h>
void swap(char *,char *);
main()
{
char name[4][10]={"amol", "robin", "shanu" };
swap(name[0],name[2]);
printf("%s %s",name[0],name[2]);
}
void swap(char *x,char *y)
{
char *temp;
temp=x;
x=y;
y=temp;
}
The main difference is the declaration of name. In your version you declare an array of pointers so you have to dereference the entries as *name[0]. In the second version it declares an array of 'char arrays' or strings and each entry holds a string, not a pointer, so you can dereference the entries as name[0]. You will see the difference clearly if you use gdb and step through the code while using the print command.

Related

converting a string to a void pointer

I'm trying to figure out how to "transform" strings (char*) to void* and viceversa.
When I execute this my output is just the first printf and ignores the second one, it doesn't even write "after = "
PS This little program is just to understand, I know i could actually use swap(&s[0],&s[1]). I need to know how to properly cast a void pointer into an array of strings.
I'm working on a uni project where I need to create my own quick_sort algorythm and I need the swap function inside of it to work with void pointers.
#include <stdio.h>
#include <stdlib.h>
static void swap(char** x,char** y);
static void swap(char** x,char** y){
char* temp=*x;
*x=*y;
*y=temp;
}
int main()
{
char* s[2];
s[0]="weee";
s[1]="yooo";
void* array=s;
printf("before %s %s\n",s[0],s[1]);
swap((&array)[0],(&array)[1]);
printf("after = %s %s",(char*)array,(char*)array);
return 0;
}
I think I'm missing something big
Thanks in advance :D
In this declaration the array s used as an initializer is implicitly converted to a pointer to its first element of the type char **.
void* array = s;
In the call of the function swap
swap((&array)[0],(&array)[1]);
the first argument can be the pointer array itself that will be implicitly casted to the pointer type of the corresponding parameter
swap( array, (&array)[1]);
But you need to correctly pass the second argument. To do this you need to cast the pointer array explicitly like
swap( array, ( char ** )array + 1 );
In the call of printf you need also correctly to supply argument expressions.
Here is your updated program
#include <stdio.h>
static void swap(char** x,char** y);
static void swap(char** x,char** y){
char* temp=*x;
*x=*y;
*y=temp;
}
int main()
{
char* s[2];
s[0]="weee";
s[1]="yooo";
void* array=s;
printf("before %s %s\n",s[0],s[1]);
swap( array, ( char ** )array + 1 );
printf("after = %s %s", *(char**)array, ( (char**)array )[1]);
return 0;
}
The program output is
before weee yooo
after = yooo weee
void *array = s; declares array to be a void *. Then &array is the address of that void *, so &array[1] would access a void * after it. But there is no void * after it, since void *array defines a single void *.
array could be properly defined to alias s with char **array = s;, after which swap(&array[0], &array[1]); would work as desired.
If you define array as void **array = (void **) s;, then swap(&array[0], &array[1]); will produce diagnostic messages because the types are wrong. You could use swap((char **) &array[0], (char **) &array[1]);.
Then, if you print the strings with printf("after = %s %s", array[0], array[1]);, this will work, although it is not entirely proper code. Using array[0] as an argument passes a void * where printf is expecting a char * for the %s. However, the C standard guarantees that void * and char * have the same representation (encode their values using bytes in memory in the same way), and it further says (in a non-normative note) that this is intended to imply interchangeability as arguments to functions.
The void* doesn't seem to fulfil any particular purpose here, just swap the pointers: swap(&s[0],&s[1]);.
You could also do this:
char** ptr = &s[0];
printf("before %s %s\n",ptr[0],ptr[1]);
swap(&ptr[0],&ptr[1]);
printf("after = %s %s",ptr[0],ptr[1]);
If you for reasons unknown insist on using void* then note that as your code stands, it points at the first char* in your array of char*. However, it isn't possible to perform pointer arithmetic on void* since that would entail knowing how large a "void" is. The void* doesn't know that it points at an array of pointers. Therefore array[i] is nonsense.
Also, the void* are set to point at char* so you simply cannot pass it to a function expecting a char**. You'd have to rewrite the whole program in a needlessly obfuscated way, so just abandon that idea.

type + pointer array size + paranthesis meaning in syntax

I have a midterm in Saturday, so our teacher gave us the previous year's midterm to help. So there is a problem that I have trouble to understand. The question is 'fill the question marks so that program outputs the string 'accioccium'.
For who do not want to spend on solving, the answers are 1,2 and spell2.
So what is happening here? Especially, what is char* (*a[3]) (char *, char *)? I mean we are creating a char pointer array but what is that paranthesis at the end?
Also, a[0] = fun1 is weird too. Yes, you can assign variables by functions. However, there is no parameter here for fun1 function. Let us say parameters are constant as *s and *p. But this time, what are they?
#include <stdio.h>
#include <string.h>
char* fun1(char *s, char *p) {
return s+strspn(s,p);}
char* fun2(char *s,char *p) {
return strcat(s,p);}
char* fun3(char *s,char *p){
return strstr(s,p);}
char* (*a[3]) (char *,char *);
int main(void) {
int i;
char spell1[10] = "accio";
char spell2[10] = "aparecium";
char* result;
a[0] = fun1;
a[1] = fun2;
a[2] = fun3;
result = (*a[?]) (spell1, "c");
printf("%s",result);
result = (*a[?]) (?, "c");
printf("%s",result);
return 0;}
Thank you for your time and help.
Especially, what is char* (*a[3]) (char *, char *) ? I mean we are creating a char pointer array but what is that paranthesis at the end?
It's an array of 3 pointers to function that takes 2 arguments pointer to char and returns a pointer to char.
The assignment a[0] = fun1 doesn't need the arguments, fun is not executed, only assigned to the compatible pointer a[0], you only add the parameters later when you actually want to execute the function, which is done for example in the line result = (*a[?]) (spell1, "c");
char* (*a[3]) (char *,char *);
Starting from a and "going clockwise" or "picking things on the right first":
a
[ is array
3]) of 3
(* pointers
(...) at end, to function
char *,char * taking two parameters of type char*
char* at the start, returning value of type char*
This matches signatures of fun1, fun2 snd fun3. and indeed array is filled with pointers to these 3 functions. Function name without () means pointer to function, it does not call the function, and using & to get address is not needed.

modify array element through pointer to a pointer

I'm trying to build a program that modifies the element of an array through a pointer to a pointer. I loaded it into the debugger and I see that the value of my pointer changes, but for some reason that doesn't affect the element in the array. Is my pointer syntax wrong? Am I reassigning my pointer somewhere else?
#include <stdio.h>
#include <stdlib.h>
#define SIZE 6
/*
*
*/
void change (char **x);
int main() {
char arra[] = "Back";
char *c = arra;
change(&c);
int i;
printf("%c", arra[0]);
}
void change (char **x) {
*x = "H";
}
*x = "H";
should be
**x = 'H';
You are trying to modify the first character and character has to be within single quotes.
There is no need of pointer to pointer here. You can just pass the array which decays to a pointer when passed in the function parameterks as shown by #haccks
No need to use pointer to pointer in this case. Just use pointer to char.
void change (char *x);
and call it as
change(c);
with the function body
void change (char *x) {
*x = 'H';
}

How Do you pass a pointer-to-an-array to a function?

How do you pass an array to a function where that function can edit it's contents?
like when doing
function(int *x)
{*x = 10;}
main()
{int x;
function(&x);}
how could i do the same using a character array?
whenever I do
function(char *array[], int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(&this, &x); }
DEV C++ says
[Warning] passing arg 1 of `function' from incompatible pointer type
obviously I did something wrong, so please tell me how to fix that. Thanks :D
You should write:
void function(char array[], int *num)
{
int x = *num;
array[x] = 'A';
}
void main()
{
char my_array[5] = "00000";
int x = 3;
function(my_array, &x);
}
Notation char *array[] is an array of pointers that you do not need here.
When you pass an array somewhere, you should not take its address. Arrays are adjusted to pointers by default.
EDIT:
Function prototypes:
void function(char array[], int *num);
void function(char *array, int *num);
are absolutely identical. There is no even minor difference between them.
Since arrays can only be passed by address, you don't really want a char * array here, just a char array:
rettype function(char *array, int *num)
{
array[*num] = 'A';
}
int main()
{
char arr[] = "1234567890";
int i = 2;
function(arr, &i);
}
In C, array names "devolve" to a pointer to the head of the array, by passing "&array", you're passing a pointer to a pointer to the head of the array, thus the warning.
char array[512];
myfunc(array, foo);
is the proper way to do what you want.
Actually you have taken one dimension array. So you can define function in two ways...
(i)
function(char array[], int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(this, &x); }
and
(ii)
function(char *array, int *num)
{ int x = *num;
*array[x] = 'A'; }
main()
{ char this[5] = "00000"; //not a string
int x = 3;
function(this, &x); }
But in your function definition, you wrote *array[] as argument which means the array is two dimensional array. So you should declare array as two dimensional array.
function(char *array[], int *num)
{ int x = *num;
//implement your code }
main()
{ char this[5][10];
// you can initialize this array.
int x = 3;
function(this, &x); }
I think it will be helpful to you.
Okay, the first thing to remember is that there's no such thing as a pointer "to an array" although you'll hear that said fairly often. It's sloppy.
(As pointed out below, the terminology "pointer to an array" does strictly have a meaning -- but I maintain that you've been confused by it. What really happens is that every pointer contains an address. Depending on the declaration, the compiler can identify if it's being used correctly in context, and that's what your error message is really telling you: what you declared in the function is a pointer to an array of chars, which is to say the same thing as a char **, instead of a char *, which is what you're passing. But char *, or char **, or char ******, the important point is that you're making it too complex -- you already have the address you need identified by the array name.)
Pointers is pointers, they're addresses.
An array in C is simply an allocated chunk of memory, and it's name represents the address of the first element. So
char a[42];
is a block of memory 42 char's long, and a is its address.
You could rewrite your second function as
void foo(char* a, int num){ // (3)
// notice that you don't need the word function and
// for lots of reasons I wouldn't use it as a function name.
a[num] = 'A'; // (4)
}
int main(){
// Sadly "00000" IS a string no matter what your comment
// says. Use an array initializer instead.
char arry[5] = {'0','0','0','0','0' } ; // (1)
foo(arry,3); // (2)
}
This does what I believe your code means to do. Note that
(1) Since "00000" really is a string, it's actually creating an array 6 elements long which could have been initialized with the array initializer
{'0','0','0','0','0', 0 }
(2) The array (which I named 'arry' instead of 'this' since 'this' is often a keyword in C-like languages, why risk confusion?) is already an address (but not a pointer. It can be on the right-hand side of an assignment to a pointer, but not on the left hand side.)
So when I call
foo(arry,3);
I'm calling foo with the address of the first element of arry, and the number 3 (you don't need to declare a variable for that.)
Now, I could have also written it as
foo(&arry[0],3);
You would read that as "find the 0-th element of arry, take its address." It is an identity in C that for any array
char c[len];
the expression c and &c[0] refer to the same address.
(3) that could also be defined as foo(char arry[], int num). Those are equivalent.
(4) and when you refer to a[num] you're referring directly to the num-th element of the memory pointed to by a, which is at the address of the start of the array arry. You don't need all that dereferencing.
Don't be disturbed that this is a little hard to follow -- it's tough for everyone when they start C.
Firstly dont use this as a variable name, its a C++ keyword. Sorry didnt realise it was a C question.
main()
{
char foo[5] = "00000"; //not a string
int x = 3;
function(foo, &x);
}
You dont take the memory address of foo. foo when used in a pointer-accepting context degrades into a pointer to the first element. *foo is the same as foo[0] which is the same as *(foo + 0)
like wise foo[3] is the same as *(foo + 3) (the compiler takes care of multiplying the element size).

Is it possible to still address the individual elements of an array via a pointer?

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;
}

Resources