how to pass array as function arguments in C? - c

how to pass array as arguments in C?
int a,b,c[10];
void Name1(int x, int y, int *z)
{
a = x;
b = y;
c = z;
}
I try to pass it as argument, but it does not build, how to fix it?
And is the declaration of void Name1(int x, int y, int *z); is the same as void Name1(int x, int y, int z[])? does the void Name1(int x, int y, int z[]) will be treated as void Name1(int x, int y, int *z); by compiler?

When you pass array as an argument to function it decays as an pointer to its first element.
So,
void Name1(int x, int y, int *z)
will work.
But arrays are not assignable so:
c = z;
does not work, you will need to explicitly copy each array element from source to destination.

Doing c = z;, you're assigning to a non l-value, which is not allowed. It's like doing &c[0] = &z[0];.

There are a couple of answers here, but I don't think any of them are completely sufficient, so...
basically you can either copy the array or use the pointer, but either way you will need to keep track of the length.
int a,b, *c, len;
void Name1(int x, int y, int *z, int z_len)
{
a = x;
b = y;
c = z;
len = z_len;
}
//usage:
int arr[5];
Name1(1,2,arr /* or &arr[0] ,*/, sizeof(arr )/ sizeof (int));
if you never need to add items this will be sufficient... If you do it gets more complicated...
it is important to keep the length around so that you know how many elements you have, even if you are going to copy them.

c=z; is invalid
c pointer doesnt have memory to save the z address.
you can say:
int a,b,*c;
c=(int *)calloc(10,sizeof(int) );
void Name1(int x, int y, int *z)
{
a = x;
b = y;
c = z;
}

Related

How do you pass a function pointer to a function in c?

#include "stdio.h"
int add(int x, int y)
{
return x + y;
}
int withFive(int x, int (*func))
{
return (*func)(x,5);
}
int main()
{
void (*funcptr)(int) = &add;
printf("%d", withFive(10,funcptr));
return 0;
}
This code seems like it would compile based on my understanding of function pointers but there is an error that a function or function pointer isn't being passed to withFive. How should I write withFive so that the compiler will accept the argument as a function ptr?
The definition should be
int withFive(int x, int (*func)(int, int ) )
or
int withFive(int x, int (*func)(int x, int y) )
like in a variable definition.
Btw: void (*funcptr)(int) = &add; should be int (*funcptr)(int,int) = &add; as well or just int (*funcptr)(int,int) = add;
int withFive(int x, int (*func))
You want, as an argument, a function func that returns int and takes two int as parameter.
So you need:
int withFive(int x, int (*func)(int, int))
Then:
{
return (*func)(x,5);
}
You don't need to dereference func. Just write
return func(x, 5);
Then:
void (*funcptr)(int) = &add;
That's the wrong type again. And you don't need to take the address of add. Just write:
int (*funcptr)(int, int) = add;
Or you could just write:
printf("%d", withFive(10,add));
Generally speaking, to make handling the somewhat awkward function pointer syntax easier and the result more readable, you could use a typedef. All together, and some other minor edits included:
#include <stdio.h>
typedef int (*binary_func_t)( int, int );
int add( int x, int y )
{
return x + y;
}
int withFive( int x, binary_func_t func )
{
return func( x, 5 );
}
int main()
{
printf( "%d\n", withFive( 10, add ) );
return 0;
}
In your case it would have to be int withFive(int x, int (*func)(int,int)). However, using the raw function pointer syntax of C is quite unreadable. The recommended practice is to always use typedefs, like this:
typedef int operation_t (int x, int y); // function type acting as "template"
int add (int x, int y);
int withFive(int x, operation_t* op); // op is a pointer to function
...
withFive(10, add);

Function Pointer with void* return and void* parameters

I wrote a function pointer that has all void* so that it can be used for any numeric value
int
float
double.
But it is working only for the int addition function
For float and double addition functions, it throws compile time error.
Why is that so ?
If you uncomment the last two printf lines, you would receive error
#include<stdio.h>
int int_add(int x, int y) {
return x + y;
}
float float_add(float x, float y) {
return x + y;
}
double double_add(double x, double y) {
return x + y;
}
void* do_operation(void* (*op)(void*, void*), void* x, void* y) {
return op(x, y);
}
void main(void) {
printf("Sum= %d\n",(int*) do_operation(int_add, 1, 2));
/*printf("Sum= %f\n",(float*) do_operation(float_add, 1.20, 2.50));*/
/*printf("Sum= %lf\n",(double*) do_operation(double_add, 1.20, 2.50));*/
}
void * is a pointer type. You're not passing pointers, you're passing values, so that's not going to compile. It accidentally "works" for int because pointers themselves are represented as integers by most C compilers.
If you pass pointers to int, float, and double instead of the int, float, and double themselves, you will avoid that compiler error. You'd also need to change int_add and friends to take pointers, and you'd have to make sure you dereferenced the pointers before using them. You'll also have to return pointers, which means you'll have to malloc some memory on the heap, because the stack memory assigned to your local variables will be invalid once your function exits. You'll then have to free it all later... in the end, this is going to result in something considerably more complicated than the problem it appears you are trying to solve.
I have to ask why you are trying to do this? C is really not the best language for this type of pattern. I'd suggest just calling the int_add, float_add, etc. functions directly instead of trying to abstract them in this way.
So as per #charles-srstka suggestion I rewrote the code and then it worked as I wanted
#include<stdio.h>
#include<stdlib.h>
int* int_add(int *x, int *y) {
int *c = (int *)malloc(sizeof(int));
*c = *(int*)x + *(int*)y;
return c;
}
float* float_add(float *x, float *y) {
float *c = (float*)malloc(sizeof(float));
*c = *(float*)x + *(float*)y;
return c;
}
void* do_operation(void* (*op)(void*, void*), void* x, void* y) {
return op(x, y);
}
void main(void) {
int a = 1;
int b = 2;
int *c;
c = do_operation(int_add, &a, &b);
printf("%d\n",*c);
free(c);
float x = 1.1;
float y = 2.2;
float *z;
z = do_operation(float_add, &x, &y);
printf("%f\n",*z);
free(z);
}

Changing values in a local scope

Does anyone know of a way I can change the values of variables that are defined locally?
#include <stdio.h>
int change(int x, int y);
int main()
{
int x = 10;
int y = 20;
change(x,y);
printf("x:%d y:%d\n", x, y);
}
int change(int x, int y)
{
x = 20;
y = 30;
return(x);
return(y);
}
I want x and y to print 20 and 30 in main().
I tried returning the values, but that didn't work. Is there another method I might be able to use? I was thinking pointers, but I don't know where to begin.
Use pointers:
void change(int *x, int *y)
{
*x = 20;
*y = 30;
}
and call the function like: change(&x, &y); For readability you may want to use different names than x and y for the change parameters as they are not of the same type as the x and y variables declared in main.
Some options:
1) Pass by refernce: int change(int &x, int &y);
2) Return an array and change current values:
int* temp = new int[2];
temp[0]=x+10;
temp[1]=y+10;
return temp;
3) Return to printf directly:
printf("x:%d y:%d\n", change(x,y)[0], change(x,y)[1]);
yes it's very easy
just pass the parameters by reference to the change function
so instead of
int change(int x, int y) >
int change(int& x, int& y)
and it will works fine

How to return two values from a function? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
returning multiple values from a function
Suppose i have passed two values to a function iCalculate(int x, int y) and this iCalculate returns two values. Those are as follows:-
(x*y)
(x/y)
Now how should i return the above two values at the same time with the same function?
My Approach was:-
int* iCalculate(int x,int y){
int temp[2];
temp[0] = x*y;
temp[1] = x/y;
return temp;
}
returning the address of the first element of a local array has undefined behavior(at least dereferencing it later is).
You may use output parameters, that is, pass two pointers, and set the values inside
void Calculate(int x, int y, int* prod, int* quot)
{
*prod = x*y;
*quot = x/y;
}
usage:
int x = 10,y = 2, prod, quot;
Calculate(x, y, &prod, &quot)
Another thing you could do is pack your data into a struct
typedef struct
{
int prod;
int quot;
} product_and_quot;
product_and_quot Calculate(int x, int y)
{
product_and_quot p = {x*y, x/y};
return p;
}
That won't work, since you're returning a pointer to a temporary array, which will stop existing at function return time.
Instead, define
typedef struct { int first, second; } IntPair;
and return an object of that type.
(This is what the standard library functions div and ldiv do, except that they call the type differently.)
Your approach is wrong, temp is out of scope/ not longer exist when functon iCalculate exit. So you must not return the address of temp. That would be address of out of scope/ no longer exist variable. Accessing that address means undefined behaviour.
You can use this approach:
void iCalculate(int x,int y,int *mult,int *divi){
*mult = x*y;
*divi = x/y;
}
or you can use another approach:
typedef struct{
int mul, divi;
} TResult;
TResult iCalculate(int x,int y){
TResult res;
res.mul = x*y;
res.divi = x/y;
return res;
}
or :
void iCalculate(int x,int y,TResult *res){
res->mul = x*y;
res->divi = x/y;
}
I suggest the first approach. I think it is too silly to create a new struct definition only to wrap 2 unrelated value together.
The way you did is wrong since int temp[2] disappears once the function returns, so the caller has a "dangling" pointer. You have to add static. Another way, likely better, is to let the caller pass where it wants the result be store e.g.
void iCalc(int x, int y, int *rp, int *rq)
{
// check if rp and rq are NULL, if so, returns
*rp = x*y;
*rq = x/y; // y != 0, and this will truncate of course.
}
and the caller will do something like
int res[2];
iCalc(x, y, res, res+1);
or similar.
Your approach was not so wrong you can return the address of the table like this :
int *iCalculate(int x,int y){
int *temp=malloc(sizeof(int)*2);
temp[0]=x*y;
temp[1]=x/y;
return temp;
}
dont forget to free the memory :
int *result;
result=iCalculate(10,7);
printf("%d %d\n",result[0],result[1]);
free(result);

Pass by reference through multiple functions

Hey all. I'm working on a project for school where I need to pass a few parameters by reference through multiple functions. I understand how I can pass by reference from where the variables are declared to another function, like this:
main() {
int x = 0;
int y = 0;
int z = 0;
foo_function(&x, &y, &z);
}
int foo_function(int* x, int* y, int* z) {
*x = *y * *z;
return 0;
}
However, how would I pass x, y, and z from foo function to another function? Something like this gives me all kinds of compiler warnings.
int foo_function(int* x, int* y, int* z) {
*x = *y * *z;
bar(&x, &y, &z);
return 0;
}
int bar(int* x, int* y, int* z) {
//some stuff
}
Just use:
bar(x, y, z);
X, Y, and Z are already pointers - just pass them directly.
Remember - a pointer is a location in memory. The location doesn't change. When you dereference the pointer (using *x = ...), you are setting the value at that location. But when you pass it into a function, you are just passing the location in memory. You can pass that same location into another function, and it works fine.
You don't need to do anything, they're already references.
int foo_function(int* x, int* y, int* z) {
bar(x, y, z);
return 0;
}
int bar(int* x, int* y, int* z) {
//some stuff
}
In foo_function x y and z are already pointers (int*), so you can do bar(x, y, z).
int foo_function(int* x, int* y, int* z) {
*x = *y * *z;
/* x, y and z are pointers to int
&x, &y and &z are pointers to pointer to int
bar expects pointers to int, so call bar as:
*/
bar(x, y, z);
return 0;
}
C has no notion of passing by reference. Parameters are always passed by value. However, when using pointers, this value is actually a pointer to your actual value.
But what you are doing with
foo_function(&x, &y, &z);
is actually trying to get an address of the pointer, which is essentially meaningless (you would pass an int** instead of an int*).
So,
foo_function(x, y, z);
would be the correct call, as x, y and z are already pointers and you don't need to make the pointing chain any longer :)

Resources