How would I pass a variable from one function to another in C? For example I want to pass the sumOfDice from function roll and use sumOfDice for the passLine function: Here is my code:
int roll()
{
int dieRollOne = (random()%6) + 1;
int dieRollTwo = (random()%6) + 1;
printf("On Dice One, you rolled a: %d\n", dieRollOne);
printf("On Dice Two, you rolled a: %d\n", dieRollTwo);
int sumOfDice = dieRollOne + dieRollTwo;
printf("The sum of you Dice is: %d\n", sumOfDice);
return sumOfDice
}
int passLine(int sumOfDice)
{
// other code
printf("the sum of dice is: %d\n", sumOfDice);
}
I would have used global variable for sumOfDice, but we are not allowed to. Would I have to pass with asterisk, like: int *num;
Nasim, this is one of the most fundamental concepts in C. It should be well-explained in any C book/tutorial you use. That said, everybody needs to learn somewhere. In order to pass values to/from a function, you start with the declaration of a function.
A function in C may receive any number of parameters but may only return a single value (or no value at all). A function requires those parameters specified in its parameter list. A function declaration takes the form of:
type name (parameter list);
The type is the return type for the function (or void). The parameter list contains the type of variables that are passed to the function. While you will normally see a parameter list in a declaration that contains both the type and name, only the type is required in the declaration. A function definition provides the function code and the function return. The parameter list for a function definition will contain both the type and name of the parameters passed.
(note: you may see old K&R function definitions without any type relying on the fact that the default type is int. That type definition/parameter list is obsolete. see Function declaration: K&R vs ANSI)
Now that you have had a Cliff's-notes version of how to declare/define a function, a short example should illustrate passing/returning values to and from a function. This first example shows the function definitions that precede the main function. In this case no separate declaration is required:
#include <stdio.h>
int bar (int x) {
return x + 5;
}
int foo (int a) {
return bar(a);
}
int main (void) {
int n = 5;
printf ("\n n = %d, foo(%d) = %d\n\n", n, n, foo(n));
return 0;
}
(note: function bar is placed before function foo because function foo relies on bar. A function must always have at minimum a declaration before it is called.)
Another example showing the common use of providing function declarations before main with the function definitions below would be:
#include <stdio.h>
int foo (int);
int bar (int);
int main (void) {
int n = 5;
printf ("\n n = %d, foo(%d) = %d\n\n", n, n, foo(n));
return 0;
}
int foo (int a) {
return bar(a);
}
int bar (int x) {
return x + 5;
}
(note: even though the function foo is defined before bar here, there is no problem. Why? Because bar is declared (at the top) before foo is called. also note: the declaration are shown with the type only, just to emphasize a point, you will normally see int foo (int a); and int bar (int x); as the declarations.)
Use/Output
The output of both is:
$ ./bin/func_pass_param
n = 5, foo(5) = 10
I hope this has cleared up some of the basics for you. If not, you can ask further, but you are far better served finding a good C book or tutorial and learning the language (at least the basics) before you attempt to compile and run a program -- it will take you far less time in the long run.
Related
I'm taking the CS50 class week 1 and I made the code work but I don't understand the custom functions part
void cat (int n)
I know that cat is your desired name for your function.
In my own understanding the code inside the parenthesis is the input that your custom function is taking (please correct me if my understanding is wrong)
but what I do not understand totally is the first word of the custom functions code like why is it void not int.
I would love it it you explained it in a much simpler English since English or programming vocabulary is pretty small atm.
Function format:
xxxxx yyyyy(zzzzz)
{
/* code */
return something;
}
xxxxx is the function return type. void means that function does not return anything to the caller.
yyyyy is the function name.
zzzzz are the function parameters. void means that function does not take any parameters. Parameters are separated by a comma. Parameter definition consists of type and parameter name.
examples:
int add(int x, int y)
{
return x + y;
}
the function add taking two integers as parameters and returning int
I do not understand totally is the first word of the custom functions
code like why is it void not int.
Programmer decided that function cat will not return anything
void cat (int n); // note the semicolon
This is a forward declaration of a function named cat that takes one int named n as an input parameter. It's declared void which means that the function does not return anything.
The definition of cat could look like this:
#include <stdio.h> // needed for printf etc.
void cat (int n) {
printf("the cat is %d years old\n", n); // note: using `n` here
// return; // not needed since the function is `void`
}
Forward declaration are made if you need to resolve circular dependencies:
void foo(int x) { if (x==1) bar(x+1); } // calls `bar`
void bar(int x) { if (x==1) foo(x+1); } // calls `foo`
This should not compile because when the compiler processes foo(), bar() is unknown. A forward declaration of bar() before foo() solves it:
void bar(int x); // forward declaration saves the situation
void foo(int x) { if (x==1) bar(x+1); }
void bar(int x) { if (x==1) foo(x+1); }
Forward declarations can also be used to declare all functions defined in the file at the top of the file and implement (define) them later. The list of functions then works as a sort of index of all the functions in the file. It's a matter of coding style. Example:
#include <stdio.h>
// forward declarations of all functions (except main):
void cat (int n);
// program entry point:
int main (void) {
cat(12); // calling cat with the argument 12 (an `int`)
return 0; // not strictly required when returning from main
}
// all the definitions follows:
void cat (int n) {
printf("the cat is %d years old\n", n); // prints: the cat is 12 years old
}
In your example, "void" is the return value of the function. In this case, the function is not defined to return a value and would therefor not have a "return" statement with a value.
Edit: But as pointed out below in a comment, it can have a "return" statement without a value.
The term has fallen out of use, but it may be more clear to (silently) regard the example given as a 'subroutine'. Whatever is done by cat() is to be done, but the perhaps many lines of fiddley code would distract from the flow of processing where cat() has been called. Putting those lines of code into a 'subroutine' means that the main body of code can be shorter and easier to understand.
Another benefit of a 'subroutine' is that the same processing can be done (called) from multiple locations without duplicating lines of code.
Here's a snippet of a contrived and trivial example I hope makes this plain. The task is to count from 0 to 'n', printing every so often, and then printing the final value reached:
#include <stdio.h>
// 'Subroutine' that provides some service
void out( int n ) {
/* this represents what could be many lines of code */
printf( "Have reached %d\n", n );
}
int main() {
int maxVal = 23; // some ceiling value
/* somewhere in the body of code */
int i = 0; // initial condition
out( i ); // output initial value
do {
i = i + 1; // processing
// output if a threshold reached
if( (i / 5) * 5 == i )
out( i );
} while( i < maxVal );
out( i ); // output final value
return 0;
}
Output:
Have reached 0
Have reached 5
Have reached 10
Have reached 15
Have reached 20
Have reached 23
I am writing some tests for my project, and the functions have the same return type but a different number of parameters. I want to use an array of function pointers to call these test functions. How to declare an array of function pointers for such functions?
The functions are declared as:
bool test1();
bool test2(char const *string, uint32_t length);
Consider that function pointers are not magic tricks, they still have to abide to the ABI calling convention, meaning that a function with a certain signature is intrinsically different from a function with a different signature.
Using a function pointer is more of a way to have dynamic methods, than to achieve polymorphism. EDIT: This is not polymorphism.
However, you can accomplish somewhat you ask by replacing each of the test functions to accept a void* and then code your parameters in a struct.
// Declare the test functions
//bool test1();
bool test1(void* struct_address)
{
// struct address unused.
}
// Parameters for test2
struct test2{
char const* string;
uint32_t* length;
}
//bool test2(char const *string, uint32_t length);
bool test2(void* struct_address)
{
struct test2 test2_s = *(struct test2*)(struct_address);
// Work with test2_s
}
// Declare the function pointer
bool (*test_ptr)(void *);
// call test1
test_ptr = test1; test_ptr((void*)NULL);
// call test2
struct test2 test2_s = {param1,param2};
test_ptr = test2; test_ptr((void*)&test2_s);
Be careful because if you pass the wrong struct type you will get memory leaks and segmentation errors. Since this is a test environment, however, this can be mitigated.
In C, an empty parameter list in a function declaration does not mean that the function takes no argument; rather, it means that it takes an unspecified number of arguments.1
So, syntactically at least, you can specify an array of function pointers, each with an unspecified number of arguments (but a fixed return type), like this: bool (*FnPtrArray[100])();. You can then assign, to different elements of such an array, addresses of functions with different argument types and numbers. However, there can then be no compile-time check that those functions are called correctly, or any implicit conversion of given argument types to the 'correct' forms.
The code below illustrates this (but note that I do not recommend using code like this, because of the inherent dangers that passing incorrect arguments can cause):
#include <stdio.h>
#include <stdbool.h>
bool Foo(int a) {
printf("Foo: %d ...\n", a);
return a % 2;
}
bool Bar(double x, double y) {
printf("Bar: %5.3lf %5.3lf...\n", x, y);
return x < y;
}
int main()
{
bool (*FnPtrArray[100])();
// So we can't tell at compile time which elements point where ...
printf("Enter a number: ");
int n = 42;
scanf("%d", &n);
if (n % 2) {
FnPtrArray[0] = Foo;
FnPtrArray[1] = Bar;
}
else {
FnPtrArray[1] = Foo;
FnPtrArray[0] = Bar;
}
// Notes assuming given "n" is odd ...
printf("%d\n\n", FnPtrArray[0](3)); // Works
printf("%d\n\n", FnPtrArray[0](3.0)); // Wrong argument type
printf("%d\n\n", FnPtrArray[1](1.0, 2.0)); // Works
printf("%d\n\n", FnPtrArray[1](1, 2)); // Wrong argument types
printf("%d\n\n", FnPtrArray[1](1.0)); // Wrong number of args
return 0;
}
Here's a link to the above code on Compiler Explorer, for those who want to test with various compilers and settings.
1 This is very different from C++, where an empty formal parameter list does mean no argument.
I have created an array of function pointers to swap two variables.
pointer pointing to these functions namely: swap1, swap2. swap3 and swap4.
swap2 is swaping using pointer passed as arguments.
but while declaring the function pointer, only int and int are passed as arguments. after compiling this causes many warnings.
so do we have a better way of passing the argument, where we put condition in function call itself.
code is given below.
#include <stdio.h>
int swap1(int ,int );
int swap2(int* ,int* );
int swap3(int ,int );
int swap4(int, int);
int swap1(int a,int b)
{
int temp=a;
a=b;
b=temp;
printf("swapped with 3rd variable :%d, %d\n", a,b);
}
int swap2(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
printf("swapped with pointer :%d, %d\n", *a,*b);
}
int swap3(int a,int b)
{
a+=b;
b=a-b;
a-=b;
printf("swapped with 2 variable :%d, %d\n", a,b);
}
int swap4(int a,int b)
{
a=a^b;
b=a^b;
a=a^b;
printf("swapped with bitwise operation :%d, %d\n", a,b);
}
int main()
{
int ch;
int a=3;
int b=4;
printf("enter the option from 0 to 3\n");
scanf("%d",&ch);
int (*swap[4])(int, int) ={swap1,swap2,swap3,swap4};// function pointer
/*can we pass something like int(*swap[4]( condition statement for 'pointer to variable' or 'variable')*/
if (ch==1)// at '1' location, swap2 is called.
{
(*swap[ch])(&a,&b);//passing the addresses
}
else
{
(*swap[ch])(a,b);
}
return 0;
}
some warnings are as follows.
at line 36 in file '9e748221\script.c'
WARNING: found pointer to int where int is expected
at line 47 in file '9e748221\script.c'
WARNING: found pointer to int where int is expected
at line 47 in file '9e748221\script.c'
Well yes. There are a number of problems with your code, but I'll focus on the ones to which the warnings you presented pertain. You declare swap as an array of four pointers to functions that accept two int arguments and return an int:
int (*swap[4])(int, int)
Your function swap2() is not such a function, so a pointer to it is not of the correct type to be a member of the array. Your compiler might do you a better favor by rejecting the code altogether instead of merely emitting warnings.
Having entered a pointer to swap2() into the array anyway, over the compiler's warnings, how do you suppose the program could call that function correctly via the pointer? The type of the pointer requires function arguments to be ints; your compiler again performs the dubious service of accepting your code with only warnings instead of rejecting it.
Since the arguments in fact provided are the correct type, it might actually work on systems and under conditions where the representations of int and int * are compatible. That is no excuse, however, for writing such code.
Because pointers and ints are unchanged by the default argument promotions, one alternative would be to omit the prototype from your array declaration:
int (*swap[4])() = {swap1,swap2,swap3,swap4};
That says that each pointer points to a function that returns int and accepts a fixed but unspecified number of arguments of unspecified types. At the point of the call, the actual arguments will be subject to the default argument promotions, but that is not a problem in this case. This option does prevent the compiler from performing type checking on the arguments, but in fact you cannot do this correctly otherwise.
Your compiler might still warn about this, or could be induced to warn about it with the right options, but the resulting code nevertheless conforms and does the right thing, in the sense that it calls the pointed-to functions with the correct arguments.
To deal with the warnings first: You declare an array of functions which take int parameters. This means that swap2 is incompatible with the type of element for the array you put it in. This will generate a diagnostic.
Furthermore, when you call one of the functions in the array, the same array declaration tells the compiler that the parameters need to be ints not pointers to int. You get two diagnostics here, one for each parameter.
To fix the above all your functions need to have compatible prototypes with the element type of the array. Should it be int or int*? This brings us to the other problem.
C function arguments are always pass by value. This means that the argument is copied from the variable onto the stack (or into the argument register depending on the calling convention and argument count - for the rest of this post, I'll assume arguments are placed on the stack for simplicity's sake). If it's a literal, the literal value is put on the stack. If the values on the stack are changed by the callee no attempt is made by the caller, after the function returns, to put the new values back in the variables. The arguments are simply thrown away.
Therefore, in C, if you want to do the equivalent of call by reference, you need to pass pointers to the variables you use as arguments as per swap2. All your functions and the array should therefore use int*. Obviously, that makes one of swap1 and swap2 redundant.
The correct array definition is
int (*swap[4])(int*, int*) = {swap1, swap2, swap3, swap4};
and the definition of each function should be modified to take int* parameters. I'd resist the temptation to use int (*swap[4])() simply because it circumvents type safety. You could easily forget the & in front of an int argument when the called function is expecting a pointer which could be disastrous - the best case scenario when you do that is a seg fault.
The others have done great work explaining what the problems are. You should definitely read them first.
I wanted to actually show you a working solution for that sort of problem.
Consider the following (working) simple program :
// main.c
#include <stdio.h>
void swap1(int* aPtr, int* bPtr) {
printf("swap1 has been called.\n");
int tmp = *aPtr;
*aPtr = *bPtr;
*bPtr = tmp;
}
void swap2(int* aPtr, int* bPtr) {
printf("swap2 has been called.\n");
*aPtr += *bPtr;
*bPtr = *aPtr - *bPtr;
*aPtr -= *bPtr;
}
int main() {
int a = 1, b = 2;
printf("a is now %d, and b is %d\n\n", a, b);
// Declare and set the function table
void (*swapTbl[2])(int*, int*) = {&swap1, &swap2};
// Ask for a choice
int choice;
printf("Which swap algorithm to use? (specify '1' or '2')\n>>> ");
scanf("%d", &choice);
printf("\n");
// Swap a and b using the right function
swapTbl[choice - 1](&a, &b);
// Print the values of a and b
printf("a is now %d, and b is %d\n\n", a, b);
return 0;
}
First of, if we try to compile and execute it:
$ gcc main.c && ./a.out
a is now 1, and b is 2
Which swap algorithm to use? (specify '1' or '2')
>>> 2
swap2 has been called.
a is now 2, and b is 1
As myself and others mentioned in answers and in the comments, your functions should all have the same prototype. That means, they must take the same arguments and return the same type. I assumed you actually wanted to make a and b change, so I opted for int*, int* arguments. See #JeremyP 's answer for an explanation of why.
I am learning C and I am studying functions. So, I read that when I implement my own function I have to declare it before the main(). If I miss the declaration the compiler will get an error message.
As I was studying this example (finds if the number is a prime number),
#include <stdio.h>
void prime(); // Function prototype(declaration)
int main()
{
int num, i, flag;
num = input(); // No argument is passed to input()
for(i=2,flag=i; i<=num/2; ++i,flag=i)
{
flag = i;
if(num%i==0)
{
printf("%d is not prime\n", num);
++flag;
break;
}
}
if(flag==i)
printf("%d is prime\n", num);
return 0;
}
int input() /* Integer value is returned from input() to calling function */
{
int n;
printf("\nEnter positive enter to check: ");
scanf("%d", &n);
return n;
}
I noticed that a function prime() is declared, but in the main, a function, input(), is called and also the function input() is implemented at the bottom. Ok, I thought it was a mistake and I change the name from prime to input.
However if I delete the declaration and I don’t put any there, the program is compiled without errors and it runs smoothly. (I compile and run it on Ubuntu.)
Is it necessary to declare a void function with not arguments?
If you don't have a forward declaration of your function before the place of usage, the compiler will create implicit declaration for you - with the signature int input(). It will take the name of the function you called, it will assume that the function is returning int, and it can accept any arguments (as Bartek noted in the comment).
For this function, the implicit declaration matches the real declaration, so you don't have problems. However, you should always be careful about this, and you should always prefer forward declarations instead of implicit ones (no matter if they are same or not). So, instead of just having forward declaration of the void prime() function (assuming that you will use it somewhere), you should also have a forward declaration of int input().
To see how can you pass any number of the arguments, consider this:
#include <stdio.h>
// Takes any number of the arguments
int foo();
// Doesn't takes any arguments
int bar(void)
{
printf("Hello from bar()!\n");
return 0;
}
int main()
{
// Both works
// However, this will print junk as you're not pushing
// Any arguments on the stack - but the compiler will assume you are
foo();
// This will print 1, 2, 3
foo(1, 2, 3);
// Works
bar();
// Doesn't work
// bar(1, 2, 3);
return 0;
}
// Definition
int foo(int i, int j, int k)
{
printf("%d %d %d\n", i, j, k);
return 0;
}
So, inside the definition of the function you're describing function arguments. However, declaration of the function is telling the compiler not to do any checks on the parameters.
Not declaring a prototype and relying on default argument/return type promotion is dangerous and was a part of old C. In C99 and onward it is illegal to call a function without first providing a declaration or definition of the function.
my question is, is it necessary to declare a void function with not arguments?
Yes. For this you have to put void in the function parenthesis.
void foo(void);
Declaring a function like
void foo();
means that it can take any number of arguments.
If prime is not used, then omit the declaration.
The code won't compile as C++, because the compiler would complain that function input is used but not declared. A C compiler might issue a warning, but C is more relaxed and does an implicit declaration of input as int input() which means that you can pass any value to input and input returns an int.
It is good style to always provide a function declaration before using the function. Only if you do this the compiler can see if you are passing too few, too many or wrongly typed arguments and how to correctly handle the return value (which might be short or char instead of int).
I'm using C to get a terminal size. That function will be call in the main function. Then I'm hoping to run it again to check if either the terminal size has changed or remain the same. This time the function are called in other function which is run_menu. For additional info, the run menu are also called in the main function. I will explain more in the code. The errors are "too few arguments to function 'get_terminal_size'.
//this function is to get the terminal size
//my idea is to use pointer as it will be use again in other function
void get_terminal_size(int *x, int* y)
{
int cols,lines;
assert(x);
assert(y);
#ifdef TIOCGSIZE
ioctl(0,TIOCGSIZE, &ts);
lines = ts.ts_lines;
cols = ts.ts_cols;
#elif defined(TIOCGWINSZ)
struct winsize ts;
ioctl(0,TIOCGWINSZ, &ts);
lines = ts.ws_row;
cols = ts.ws_cols;
#endif
*x = cols;
*y = lines;
}
//this function is to see either the size has changed or not
int change_terminal_size()
{
int new_cols, new_lines;
int x, y;
get_terminal_size(&x, &y);
#ifdef TIOCGSIZE
ioctl(0,TIOCGSIZE, &ts);
new_lines = ts.ts_lines;
new_cols = ts.ts_cols;
#elif defined(TIOCGWINSZ)
struct winsize ts;
ioctl(0,TIOCGWINSZ, &ts);
new_lines = ts.ws_row;
new_cols = ts.ws_cols;
#endif
log_debug("new lines=%d,new cols =%d",new_lines,new_cols);
if((new_cols !=x)||(new_lines != y)){
return 1;
}
return 0;
}
//this function is to run the menu.
static void run_menu()
{
//bla bla bla with other declaration and function
//i will not write it because its not related
while(1){
if (change_terminal_size()){
log_debug("the terminal has change size");
}
//and it will continue with other things
//this is the main function
int main()
{
//again with other declaration and function not related
get_terminal_size();
run_menu();
//continue on with other thing, then return 0
}
As you can see. I call the "get_terminal_size" function 2 times. Is it related to the problem that im having? As far as I know, if I'm using a pointer, then it shouldn't be any problem.
In here:
//this is the main function
int main()
{
get_terminal_size(); //<---Right here!
run_menu();
}
You don't pass any arguments to get_terminal_size.
get_terminal_size expects to be called with two arguments, thus the error "Too few arguments to function".
"Using a pointer" doesn't really have anything to do with it, nor does "Using a pointer" allow you to use the function from multiple places. All the pointers (x and y) do is allow the function to change values outside of its scope.
Sidebar: you probably ought to have get_terminal_size return a value - in this case probably a struct with an X field and a Y field. Functions that return values via side-effect are more difficult to reason about and more likely to contain bugs, although this particular example is probably fine since you're not mixing input arguments with output arguments.
Also your change_terminal_size() function looks pretty gnarly. Where are you keeping track of the old terminal size so you can compare it to the new terminal size?
get_terminal_size(int*, int*) is a function with two parameters of type int*. In order to call this function, you must pass it the appropriate number of arguments each with the correct type. In main, you call it with no arguments and your compiler complains, as it should.
The main function will need to pass some appropriate arguments - something like below:
int main()
{
//again with other declaration and function not related
int x = 0, y = 0;
get_terminal_size(&x, &y); // &x and &y both have type int*
run_menu();
//continue on with other thing, then return 0
}
You are calling a function which takes two parameters, but you are not using any parameters when you do it. You do use the correct number of parameters in change_terminal_size, which is why that function succeeds.
The good news, though, is that since get_terminal_size does not affect the outside world, you can replace main with:
int main()
{
run_menu();
return 0;
}