How to declare parameters (which depend on one another ) in C - c

I have a bunch of parameters (integers and floats); I want to write a C code where both the main program and the functions refer to the same parameters so that if I change one of them the whole code knows the new value I set. My code is formed by a main.c file which calls a function.c file; right now I declared the parameters both in the main and in the function but I think that is not robust (if I change one parameters in the main and I forget to change it also in the function I get wrong results). So here is the question: How can declare the parameters in order to change it just once and not to change it everywhere I have defined?
PS: some of the parameters depend from some others that have been previously declared
Here's what I did: I created a myparameters.h file where I declare my parameters like this: extern float x;
then I created a myparamter.c file where I define the value of the parameter: float x = 10;
However some of the parameters I define depend from others: float a = a + b; and therefore I get an error message like this one:
warning: initializer element is not a constant expression

Terminology Clarification
What you're talking about are global variables, not parameters. The word "parameters" refers to input arguments to a function:
int my_function(int arg1, char arg2) {
That is how you should be passing arguments to your functions, not through global variables.
Your Error
You're getting the error because you're trying to initialize a global variable outside of a function with a value that is not necessarily known at compile time:
int a = 2; /* legal */
int b = a + 2; /* not legal */
int main(){ /* the rest of your code */
Globals can only be initialized by constants, macros, and hardcoded values:
int a = 2; /* legal */
int b; /* also legal */
int main(){
b = a + 2; /* now that you're in a function, you can make your assignment */

Related

Global variables as arguments in function C

I have a list of global variables like this:
int a, b, c, d;
These variables are used in functions designed to count them, like:
int my_func(string x)
{
//count var a//
}
Now I would like to use 'a' and e.g. 'b' as an arguments for another function which I declare this way:
int multiplication(int a, int b);
and define this way:
int multiplication(int a, int b)
{
c = a * b;
return c;
}
When I run it, I get the below error:
ac.c:75:27: error: declaration shadows a variable in the global scope [-Werror,-Wshadow]
int multiplication(int a, int b)
^
ac.c:7:41: note: previous declaration is here
int a, b, c, d;
How can I fix it? When I try to declare those variables inside functions, the whole program returns many errors.
You cannot use global variables as parameters of a function. That would make no sense either.
int multiplication (int a, int b)
What happens here in truth is that a and b are two separate function-local variables inside of the function multiplication.
They are not references for the global variables with the same names.
As function-local variables have higher priority, they shadow the global variables at the scope of the function, which means that if you use/address a or b inside of the function, they refer to the local variables, not the global ones.
That's what the diagnostic of:
"declaration shadows a variable in the global scope"
says to you. The declaration of the local variables shadows the global variable declarations inside of the function multiplication.
What you can do is pass the global variables as arguments by value to the function multiplication:
#include <stdio.h>
int multiplication (int a, int b);
int a = 5, b = 10, c = 15, d = 20;
int main (void)
{
printf("Product: %d", multiplication(a,b)); // arguments, global variables.
}
int multiplication (int a, int b) // parameters, local variables.
{
return a * b;
}
Output:
Product: 50
In this way shadowing still occurs but it isn't problematic, if you add the specific -Wno-shadow flag to turn off warnings/errors for shadowing. This is usually only a warning to hint you that shadowing occurs. Shadowing itself is not harmful.
That it is treated as error is caused by the -Werror flag, which displays warnings as erros. -Werror is great, but you should be able to differentiate real errors (issues that won't get the code compiled anyway) and only warnings which are just shown as errors to prevent code being executed with any reasonable things which potentially can give you issues with regard to the successful implementation of the algorithm or the execution.
Or just rename the parameters to a different name to make the compiler not show these warnings.
If you only want to use global variables inside of the function multiplication, you could just use c = a * b; inside of main() and omit the whole function multiplication then:
#include <stdio.h>
int a = 5, b = 10, c = 15, d = 20;
int main (void)
{
c = a * b;
printf("Product: %d", c);
}
Output:
Product: 50
To use a function which changes only global variables is considered as bad practice.
Side notes:
You should avoid global variables whenever possible, where you could pass values either by value or by reference as arguments instead.
If you got a lot of functions, where you need to pass the value of the same variable into it would make sense to use global variables.
Also as you seem to confuse the terms "argument" and "parameter", take a look at here:
What's the difference between an argument and a parameter?

How can I solve this simple C function?

I am taking a hybrid class of "Algorithms, architecture, and assembly language" at my local community college. Although it's an intro class and mainly focuses on how computers turn code into binary, we have some assignments for C code. Some of the stuff we've never even gone over in class, and I'm lost.
The instructions read:
Write a function named DoSomething, with no return value, it should do just one (1) thing: multiply the global variable my_result by 5 and store the result back into my_result
You do not have to call DoSomething, or initialize my_result, I will do that.
I have tried
int my_result;
dosomething (my_result) {
my_result = my_result * 5;
}
but this is incorrect. I have almost zero experience with C language and am stuck. I'm not asking anyone to do my homework, I just want to understand. This has not been covered in class.
You almost have it. Since my_result is global, you do not need to pass it into the function, it is accessible everywhere. Oh, and every function needs its return value specified. Use void to specify that there is no return value and no parameters.
int my_result;
void dosomething (void) {
my_result = my_result * 5;
}
A correct function declaration must have a type, the name of the function and its arguments.
type function_name(type1 arg1, type2 arg2, type3 arg3, ...);
If a function does not return anything, then type must be void
void function_name(type1 arg1, type2 arg2, type3 arg3, ...);
If a function does not take any parameter, then the you can use void instead
of the list of arguements:
type function_name(void);
Your dosomething function is missing the return type, which should be void
(assignment says Write a function named DoSomething, with no return value)
and it takes no arguments (at least the assignment does not specify any), so the
correct prototype of the function must be:
void DoSomething(void);
So the correct program
#include <stdio.h>
int my_result;
void DoSomething(void)
{
my_result = my_result * 5;
}
int main(void)
{
my_result = 6; // initializing global variable
DoSomething();
printf("my_result: %d\n", my_result);
return 0;
}
which will print my_result: 30.
There is nothing to get worried about. Relax, it's just part of the process in becoming a good developer.
To solve such problems, first note what the function expects and we want from the function to return.
Now, in your question, it is given that function would return nothing. So the return type of the function would be void.
Now, since we have to use a global variable, it means function expects no argument.
Hence, our code is :
#include <stdio.h>
int my_result; // Our Global Variable
void doSomething (void) // Our Function
{
my_result = my_result * 5;
}
int main()
{
/* Asking the value of my_result */
printf("Please enter a value : ");
scanf("%d", my_result);
doSomething();
printf("\nNew value of my_result is : %d\n", my_result);
return 0;
}
// End of main.
The instructions read:
Write a function named DoSomething, with no return value,…
So code for that is:
void DoSomething(void)
… it should do just one (1) thing: Multiply the global variable my_result by 5 and store the result back into my_result.
And code for that is:
{
my_result = my_result * 5;
}
You do not have to call DoSomething, or initialize my_result, I will do that.
Done. The total code requested is:
void DoSomething(void)
{
my_result = my_result * 5;
}
You have indicated in your comments that you are submitting this code into some sort of automatic grading/checking software. So that software is designed to accept code that matches the assignment, no more and no less. Quite likely, it puts your code into a file and that compiles a source file that includes the former file with #include. That source file defines my_result and main, so your code should not, or it will cause compilation and/or link errors. You need to submit just the code requested in the instructions.
Notes about your code:
The instructions say to write a routine named DoSomething. You used dosomething. These are different in C; the case matters.
You declared the routine without specifying a return type. The instructions say the instruction has no return value, but that does not mean you should just omit any return type. You should explicitly say there is no return value by using void for the return type of the function, as in void DoSomething(…). (For historic reasons, if you omit the return type in a function declaration, it defaults to int. Letting the type default like that is old syntax and should be avoided.)
The instructions did not say whether the routine should take parameters. This is a shortcoming in the instructions. However, dosomething (my_result) is incorrect for two reasons. One, my_result is described as a global variable, not a parameter. Two, it is the wrong syntax for a parameter declaration. A parameter declaration must have a type, as in dosomething(int x). Since the routine needs no parameters, a proper declaration is void DoSomething(void). (Although there is some possibility the instructor intended void DoSomething(), but that would not generally be preferred.)

How to allow variable parameters passed to function

I have a function that accepts 3 parameters, however I also want it to only accept the first two and not care about the third. How can I do this in C. I tried just declaring the function in the header file as void list()
thinking this might imply that we don't care how many parameters but this didn't work.
void list(uint8_t _pin, unsigned int time, unsigned long tasks)
What you want is called Variadic function. It can accept variable number of arguments.
**Famous examples: printf()/scanf()
These functions contain an ellipsis (…) notation in the argument list, and uses special macros to access the variable arguments.
The most basic idea is to write a function that accepts a variable number of arguments. So, it must be declared with a prototype that says so.
The syntax of ISO C requires at least one fixed argument before the …. thus, we write the fixed arguments as usual, and then add the … notain at the end of the parameter list to indicate the possibility of additional arguments. For example,
int func (const char *a, int b, …)
{
…
}
defines a function func() which returns an int and takes two required arguments, a const char * and an int. These are followed by any number of anonymous arguments.
You can check the On-line GNU manual for more details.
Here is a trick explained in SO here : C default arguments.
You can make third parameter as default in function declaration as follows:
typedef struct {
uint8_t _pin;
unsigned int time;
unsigned long tasks;
} f_args;
double var_f(f_args in){
uint8_t _pin = in._pin? in._pin : 8;
unsigned int time = in.time ? in.time : 3;
unsigned long tasks =in.tasks? in.taska : 0;
return f_base(i_out, x_out);
return list(_pin, time, tasks);
}
#define list(...) var_f((f_args){__VA_ARGS__});
So you can call your function as follows:
list(2,5);
A different solution to your problem without variable parameters is to do something like this:
void list(int argc, char **argv);
You have two parameters always, however what changes is the contents of argv and the count of what is inside it. You might have seen this in the entry point (main function) of other C programs. The parameters argc, argument count, and argv, argument vector, give the number and values of what you need.
Then inside list you could do something like:
if (argc == 2)
do_something;
else if(argc == 3)
do_something_else;
else
whatever;

What happens if i declared another variable with the same name in another file?

I have declared int x in file one and by mistake I declared another variable of type char with the same name x in file two, and I wait the compiler or the linker to give me an error, but there are no errors displayed. and when I use the debugger I see that int x is converted to char x , is that true?! and what actually happens here?!
Show this modification on my code:
File One
#include <stdio.h>
int x = 50; /** declare global variable called
x **/
int main()
{
print();
printf(" global in file one = %d",x); /** Modification is just here **/
return 0;
}
File Two
char x;
void print(void)
{
x = 100;
printf("global in file two = %d ",x);
return;
}
My expected results are = global in file two = 100 global in file one = 50
but The results are : global in file two = 100 global in file one = 100
When I use the debugger I see that int x is converted to char x , is that true?! and what actually happens here?
You're in troublesome territory here. Technically your program causes undefined behaviour. char x is a tentative definition, since it doesn't have an initializer. That means the linker unifies it with the int x in the other file at link time. It's a bit weird looking, since your two declarations have different types, but it appears to have successfully linked in your case. Anyway, you have only one x, and luck is making it work the way you're seeing it (and little-endian architecture, probably).
If you want the two variables to be independent, make them static, and they'll be restricted to the scope of their respective translation units.

How to define an array of function pointers and the functions don't have same input argument definition?

Is it possible to define an array of function pointers (and the functions don't have se same input argument ) as indicating in the following code ?
If yes what I have to put in the function definition int (*handler)(/*what Ihave to put here ?*/);
struct handler_index {
const char *name;
int (*handler)(/*what Ihave to put here ?*/);
};
int handler0 (int a, int b)
{
printf("%d\n",a+b);
}
int handler1 (int a, int b, int c)
{
printf("%d\n",a+b+c);
}
int handler2 (int a, int b, int c, int d)
{
printf("%d\n",a+b+c+d);
}
const struct handler_index handler_index[] = {
[0] = {"handler0", handler0},
[1] = {"handler1", handler1},
[2] = {"handler2", handler3},
};
Just put nothing:
int (*handler)();
it means the function has an unspecified (but non-variable) number and types of parameters.
Any function that returns an int and with a fixed variable number of parameters can be assigned to handler.
Whilst int (*handler)() will indeed allow variable number of arguments for th function, I fail to see any benefit in this. Function pointers are useful when you have a piece of code that takes something, finds the "right thing to do" (e.g comparing the "name" with some input from elsewhere), and calls the function pointer to do whatever it has to do. The function pointer calling code needs to know how many arguments the function has (how else would it pass the right number and order of arguments.
I don't actually see any meaningful use of this at all. Yes, you can pass a variable number of arguments to a function, but the code HAS to know what arguments the function takes.
Unless the arguments are somehow specified in the definition of the struct - but then you need to define different content for the struct to allow for that.
I would suggest that you need to think about what you are trying to achieve, and then come up with a solution to the problem, most likely using a different method.
Put nothing. Just empty brackets.
int (*handler)();

Resources