pointers and functions - c

how to return more than one value from a function?

A function can only have a single return value. You could either pack multiple values into a compound data type (e.g. a struct), or you could return values via function parameters. Of course, such parameters would have to be passed using pointers to memory declared by the caller.

1
Declare method like this foo (char *msg, int *num, int *out1, int *out2);
and call it like this
int i=10;
char c='s';
int out1;
int out2;
foo(&c,&i,&out1,&out2);
Now what ever values u assign to out1 and out2 in function will be available after the function returns.
2
Return a structure having more than one members.

In C, one would generally do it using pointers:
int foo(int x, int y, int z, int* out);
Here, the function returns one value, and uses out to "return" another value. When calling this function, one must provide the out parameter with a pointer pointing to allocated memory. The function itself would probably look something like this:
int foo(int x, int y, int z, int* out) {
/* Do some work */
*out = some_value;
return another_value;
}
And calling it:
int out1, out2;
out1 = foo(a, b, c, &out2);

You cannot return more than 1 value from a function. But there is a way. Since you are using C, you can use pointers.
Example:
// calling function:
foo(&a, &b);
printf("%d %d", a, b);
// a is now 5 and b is now 10.
// called function:
void foo(int* a, int* b) {
*a = 5;
*b = 10;
}

Functions can return arrays or lists

Related

Accessing variable value without declaring it in function prototype

In the function read, I need to access the values of integer a and integer b from the main function without declaring them in the prototype of the function read, using pointers.
Pointer x should point to integer a, and pointer y should point to integer b.
#include <stdio.h>
void read(int zzz[], int n) {
int *arr = zzz, *x=a,*y=b;
}
int main() {
int a, b;
scanf("%d", &a);
scanf("%d", &b);
return 0;
}
How this could be implemented?
There are two ways that the read function can read the values or addresses of a and b:
Pass them as parameters
Make a and b global
So if you don't want to make them parameters, you need to move them outside of the main function and before the read function.
Also, read is the name of a system function, so you should name it something else so you don't conflict with it.
You have already received the more conventional answer. It is the most logical choice for your given restriction.
However ... Silly artificial restrictions sometimes deserve a silly contrived solution in kind.
A less conventional way would be to create an understanding with the function that the values will be passed in with the array pointer in some non-standard way.
For example, you can make two extra array members to represent a and b.
int array_for_my_read[array_size + 2];
/* instead of a and b, you use those extra array members */
...
int *x = zzz + n, *y = x + 1;
Alternatively, you could create a special structure that holds the array, and the pointers. Then the function recovers the pointer to the structure from the array pointer.
struct extra_parameters {
int *a;
int *b;
int zzz[zzz_size];
};
...
struct extra_parameters x;
int a, b;
x.a = &a;
x.b = &b;
read(x.zzz, zzz_size);
...
void *p = (char *)zzz - offsetof(struct extra_parameters, zzz);
struct extra_parameters *xp = p;
int *a = xp->a, *b = xp->b;

Why is my output 5 and 0 instead of 6 and 5

Why my code output is 5 and 0, not 6 and 5?
I think I should get 6 and 5. I am a beginner.
#include <stdio.h>
int swap(int a,int b);
int main()
{ int x =5;
int y =6;
printf("%d %d\n",x,y);
int number[2]={swap(x,y)};
x=number[0];
y=number[1];
printf("%d %d\n",x,y);
return 0;
}
int swap(int a,int b)
{
return b,a;
}
There are several things wrong here.
First, you can't return multiple values in C, like you can in Python. return b, a; uses the comma operator, which evaluates both its operands and returns the second one. So this is equivalent to just return a;.
Second, your array initializer is only initializing the first element of the array. There's only one expression in the initialization braces, so that initializes number[0]. The remaining elements of the array are initialized by default to 0.
Combining both of these, it's equivalent to:
int number[2] = {y, 0};
I can see you are new to C programming. The problem is in your swap() function. You're using a language construct that does not exist in C, namely tuples. Check out pointers for a proper way to return multiple values from a function.
This function ...
int swap(int a,int b)
... returns one int, as its prototype says.
This statement ...
return b,a;
... involves C's comma operator ,, which evaluates its left-hand operand, discards the result, then evaluates to the value of its right-hand operand. Since evaluating b has no side effects in your case, that return statement is equivalent to
return a;
In C, it is valid to initialize an array with fewer explicit elements than the length of the array. For an automatic (local, non-static) array such as yours, as long as at least one element is initializer, all elements not explicitly initialized are implicitly initialized (to 0 in the case of int elements). Thus, for your implementation of swap(), this ...
int number[2]={swap(x,y)};
... is equivalent to
int number[2] = { x, 0 };
, which explains the output.
Here is a way to solve your problem.
#include <stdio.h>
void swap(int *a,int *b);
int main()
{
int x = 5;
int y = 6;
swap(&x, &y);
printf("post swap x = %d, y = %d\n", x, y);
return 0;
}
// No need to return anything, we change the x, y values using the pointer
// This is passing by reference. Instead of passing the value, we are
// passing the reference (i.e address of the variable). swap function can
// now directly access the values and change them
void swap(int *a, int *b)
{
int tmp;
printf("Swap got a = %d, b = %d\n", *a, *b); // Note: we access value of a pointer using * in front of the pointer varaible
tmp = *a;
*a = *b;
*b = tmp;
}
outputs:
bhakta: /tmp$ cc x.c
bhakta: /tmp$ ./a.out
Swap got a = 5, b = 6
post swap x = 6, y = 5

update actual values using pass by value

I want to know if there is any way to update original values by using pass by value.
Also i want to know if I can return updated address back to main
Here I dont want to use pass by reference to swap original values in main.
#include<stdio.h>
int a = 100;
int f =200;
int *p, * q;
swap(int, int);
main()
{
printf("%d %d\n", a,f);
swap(a, f);
printf("%d %d\n",a ,f); //values remain same here how to change them
}
swap(int a, int f)
{
int t;
p=&a;
q=&f;
t=*p;
*p=*q;
*q= t;
printf("%d %d\n",a ,f);
}
I want to know if there is any way to update original values by using pass by value.
Yes there is, you need to pass a pointer:
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
And call it like this:
swap(&a, &f);
Note that there's no pass-by-reference in C, that's a C++ feature. In C everything, including pointers, are passed by value.
And pass-by-value means copy in C, so it's impossible to modify what was passed.
Also i want to know if I can return updated address back to main
Yes you can. Just change the function return type to a pointer type and add a return statement with the address of the variable of your choice.

C pointer referencing another pointer in functions

I discovered that if you assign a pointer address to another pointer's address in a FUNCTION it won't change the in value in the main,
however by doing the same thing in main, it will change. So what is the reason of this?
void func(int *a, int *b){
b = a;
}
int main(){
int i= 5, k =6, *a=&i, *b=&k;
printf("%d %d\n",*a,*b); //output 5 6
b = a;
printf("%d %d\n",*a,*b); //output 5 5
a=&i;
b=&k;
func(a,b);
printf("%d %d\n",*a,*b); //output 5 6
printf("%d %d\n",*a,*b); //output 5 6
}
In this function
void func(int *a, int *b){
b = a;
}
parameters a and b are local variables of the function. After exiting the function they will be destroyed. The function deals with copies of arguments. If you want that the function would change the original arguments themselves you have to pass pointers to them. For example
void swap(int **a, int **b){
int *tmp = *a;
*a = *b;
*b = tmp;
}
Your function:
void func(int *a, int *b){
b = a;
}
doesn't do anything, it just takes two values representing memory addresses as parameters and assigns one to the other without any external effect whatsoever. It just writes the value of the one to the other (probably not even that, because the compiler will likely detect this is pointless and eliminate it altogether), it doesn't do anything with the information stored at those addresses. You will need to deference the pointer to read or write to the memory address it holds the value of, but in the present form, the function will not assign the pointer to the other, but the value of i to k.
If you want a function to change a parameter outside of it, you should pass by reference, which in C is just pass by pointer, so you need to pass a pointer to the pointer, not the pointer - which will pass a copy of that pointer - the same value, while passing as pointer to pointer will pass the address of the pointer in memory, not the value it holds.
So it should be:
void func(int **a, int **b){
*b = *a;
}
and func(&a,&b) and you will reproduce what you do in main via b = a.

assignment after function returning array of pointers

Here is the code which i got confused with.It would be great help if someone corrected this code?
int (*(x)())[2];
int main()
{
int (*(*y)())[2]=x;
x();
return 0;
}
int (*(x)())[2]
{
int **str;
str=(int*)malloc(sizeof(int)*2);
return str;
}
How to assign an array of pointers when returned by x?is using malloc only solution?
Thanks in advance
It's not entirely clear what you're trying to accomplish, so I'll cover more than one possibility.
First of all, a refresher on how to read and write complicated declarations in C:
Remember that () and [] have higher precedence than unary *, so *a[] is an array of pointers, while (*a)[] is a pointer to an array; similarly, *f() is a function returning a pointer, while (*f)() is a pointer to a function.
When you're trying to read a hairy declaration, start with the leftmost identifier and work your way out, remembering the rule above. Thus,
int (*(x)())[2];
reads as
x -- x
(x) -- x
(x)() -- is a function
*(x)() -- returning a pointer
(*(x)())[2] -- to a 2-element array
int (*(x)())[2] -- of int
In this case, the parens immediately surrounding x are redundant, and can be removed: int (*x())[2];.
Here's how such a function could be written and used:
int (*x())[2]
{
int (*arr)[2] = malloc(sizeof *arr); // alternately, you could simply write
return arr; // return malloc(sizeof (int [2]));
} // type of *arr == int [2]
int main(void)
{
int (*p)[2] = NULL; // alternately, you could write
... // int (*p)[2] = x();
p = x();
...
free(p);
}
Notice that the declarations of arr, p, and x() all look the same -- they all fit the pattern int (*_)[2];. THIS IS IMPORTANT. If you declare one thing as T (*p)[N] and another thing as T **q, then their types are different and may not be compatible. A pointer to an array of T is a different type than a pointer to a pointer to T.
If your goal is to create an array of pointers to functions returning int, then your types would look like int (*f[2])();, which reads as
f -- f
f[2] -- is a 2-element array
*f[2] -- of pointers
(*f[2])() -- to functions
int (*f[2])(); -- returning int
That would look something like the following:
int foo() {...}
int bar() {...}
int main(void)
{
int (*f[2])() = {foo, bar};
...
}
If you want a function that returns f, that's a little trickier. C functions cannot return array types; they can only return pointers to arrays, so your function declaration would be built up as
g -- g
g() -- is a function
*g() -- returning a pointer
(*g())[2] -- to a 2-element array
*(*g())[2] -- of pointers
(*(*g())[2])() -- to functions
int (*(*g())[2])() -- returning int
And such a beastie would be used something like this:
int foo() {...}
int bar() {...}
int (*(*g())[2])()
{
int (*(*f)[2])() = malloc(sizeof *f);
(*f)[0] = foo; // the type of the *expressions* foo and bar
(*f)[1] = bar; // is `int (*)()`, or pointer to function
return f; // returning int
}
int main(void)
{
int (*(*p)[2])();
int x, y;
...
p = g();
x = (*(*p)[0])();
y = (*(*p)[1])();
...
free(p);
...
}
Note that you can also build up hairy declarations from the outside in, using a substitution method. So,
int x(); -- x is a function returning int
int (*p)(); -- replace x with (*p) to get a pointer to a function
returning int
int (*a[2])(); -- replace p with a[2] to get an array of pointers
to functions returning int
int (*(*q)[2])(); -- replace a with (*q) to get a pointer to an array
of pointers to functions returning int
int (*(*g())[2])(); -- replace q with g() to get a function returning
a pointer to an array of pointers to functions
returning int.
Same result, different path. I prefer the first method, but either one should work.
Many people recommend using typedef to make things easier to read:
typedef int ifunc(); // ifunc is a synonym for "function returning int"
typedef ifunc *pifunc; // pifunc is a synonym for "pointer to function
// returning int
typedef pifunc farr[2]; // farr is a synonym for "2-element array of
// pointer to function returning int
typedef farr *pfarr; // pfarr is a synonym for "pointer to 2-element
// array of pointer to function returning int
pfarr g()
{
pfarr f = malloc(sizeof *f);
(*f)[0] = foo;
(*f)[1] = bar;
return f;
}
int main(void)
{
pfarr p = g();
int x, y;
x = (*(*p)[0])();
y = (*(*p)[1])();
...
}
Yes, the declarations are easier to read, but there's no connection between the declaration of pand the expression (*(*p)[1])(). You'd have to grovel back through all the typedefs to understand why that expression is written the way it is, building up a mental map for each typedef.
Yes, declarations like int (*(*g())[2])() are designed to make your eyes glaze over, hiding all that behind a typedef makes the situation worse IMO.
Don't understand what you want to do, maybe this can help
#include<stdio.h> // printf
#include<stdlib.h> // malloc free
int *x(); // forward declaration because used before definition
int main() {
int *y=x(); // y is a pointer on int
printf ("%d %d\n", y[0], y[1]);
free(y); // must call free because dynamic allocation
return 0;
}
int *x() {
int *res;
res=(int*)malloc(sizeof(int)*2); // dynamic allocation of an array of two int
// should check res != NULL
res[0]=10;
res[1]=20;
return res;
}
This following code will give you an array of pointers to functions, and standard procedures for assigning, passing of arrays applies.
#include <stdio.h>
#include <stdlib.h>
typedef int (*XFunc())();
XFunc *x[2]; /* array of XFunc pointers */
int f1()
{
printf("1\n");
return 1;
}
int f2()
{
printf("2\n");
return 2;
}
int main()
{
x[0] = (XFunc*)f1;
x[1] = (XFunc*)f2;
x[0]();
x[1]();
return 0;
}
The pointer x above will point to the first element in the (fixed) array, this pointer-value is the value that will be assigned to another variable.

Resources