Why do you skip void function calls without catching them? [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I want to call a function that calculates the width of a circle.
#include <stdio.h>
void area(double*);
int main()
{
void* vp = NULL;
double r;
printf("input value : ");
scanf(" %lf", &r);
(double*)vp = &r;
void area(vp);
}
void area(double* dp)
{
double result;
result = (*dp) * (*dp) * (3.14);
printf("circle are is : %.2lf", result);
return 1;
}*
I want to call a function in the //void area (vp)//, but I can not catch the error in visual stdio and proceed as it is. Do you know what the cause is?

To call the function, you write area(vp); not void area(vp);.
The latter, as it appears in the function main, is a function prototype and has no run-time effect.
And fix that definition of PI: yours is terribly inadequate given that you use a double type. See Math constant PI value in C

You should write
area(&r);
instead of the wrong and superfluous
void area(vp);
Adding to the obvious mistake you made in the syntax
I don't see any reason for vp to be there.
to ensure success for scanf(), always check for the return value of the call.
Quoting C11, chapter §6.8.6.4,
A return statement with an expression shall not appear in a function whose return type
is void. [....]

There are three problems with the code.
For starters it is unclear why the pointer vp is declared as having the type void * though in the program it is used only to point objects of the type double.
Why not to declare it like
double *vp = NULL;
As result this trick with the pointer
(double*)vp = &r;
will not compile because in the left side the expression (double*)vp is rvalue and may not be assigned.
You could just write
vp = &r;
The second problem is that this statement
void area(vp);
is also invalid. To call the function you should write
area(vp);
And the third problem is that a function that has the return type void shall not specify an expression in the return statement
This statement shall be removed.
return 1;
From the C Standard (6.8.6.4 The return statement)
1 A return statement with an expression shall not appear in a
function whose return type is void. A return statement without an
expression shall only appear in a function whose return type is void.
There is no sense to declare the parameter of the function as having a referenced type.
The function definition could look like
double area( double dp )
{
const double PI = 3.14;
return dp * dp * PI;
}
The statement with the call pf printf should be moved in main
printf( "circle are is : %.2lf", area( r ) );

Related

False positive "Null Dereference" error in Fortify for function call [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am running Fortify SCA and Applications 21.1.1 on a C project and I'm obtaining a "Null pointer dereference" error in the following line:
int parameter1 = 1;
char *parameter2;
int foo = 1;
sprintf(parameter2, "%d", foo);
pFunction(parameter1, parameter2, NULL);
In a header file, pFunction is declared as:
typedef int(*Function)(int a, char* b, char* c);
extern Function pFunction;
pFunction definition is in an external file which I don't have access to.
I am pretty sure that is a false positive error in Fortify. Is there a suitable workaround for this?
The variable parameter2 declared like
char *parameter2;
either is uninitialized and has an indeterminate value if it is declared in a block scope or represents a null pointer if it is declared in the file scope.
In the both cases if the first argument of a function call is equal to 1 then this statement
memset(b, '*', strlen(b));
invokes undefined behavior.
Pay attention to that the typedef declaration of the function pointer type
typedef int(*Function)(int a, char* b, char* c);
does not correspond to the function declaration
void pFunction(int a, char *b, char *c)
They differ in the return type.

why does my gcc allow this empty function with pointer return type? [duplicate]

This question already has answers here:
Why does this C++ snippet compile (non-void function does not return a value) [duplicate]
(7 answers)
Closed 2 years ago.
The following function successfully compiles and prints hello 5 on gcc 8.3 running on Debian:
#include <stdio.h>
int* bar(int* x) {}
int main() {
int x = 5;
int* p = bar(&x);
printf("hello %d\n", *p);
}
I'm confused about the function bar. It's declared as int* but the body is empty, so I didn't actually tell it to return anything. More concerning, why does the program behave as if I had said return x; in the body of bar? Is this behavior that is specified somewhere or is it just an accident?
The C standard does not require a function declared with a non-void return type to return a value.
The standard says that if a function returns without returning a value (because execution flows to its closing }) and the value of the function is used, then the behavior is not defined. However, there are situations where it makes sense for a function to return a value in some cases and not others. For example, you can have a function that sets or gets a value depending upon a command parameter:
int AccessState(int Command, SomeStructure *S,...)
{
switch (Command)
{
case 0: // Get the state.
return S->Value;
case 1: // Set the state from the optional int parameter following S.
va_list ap;
va_start(ap, S);
S->Value = va_arg(S, int);
va_end(ap);
break;
}
}
Doing this is unusual (and may not be good design), so a compiler may warn about it. However, to conform to the C standard, a C implementation must not reject a non-void function in which control may reach the closing }.
The standard has the following to say about return statements:
ISO/IEC 9899:2018 §6.8.6.4 The return Statement passage 2
A return statement terminates execution of the current function and returns control to its caller. A
function may have any number of return statements.
This means that the compiler has to allow non void functions that have no (or no reachable) return statement, in order to be in compliance with the standard.
This leaves the return value as undefined behavior.
In this case the register used for the first function argument is also the register used for the return value.

Passing float to a function with int argument (that is not declared beforehand)

I have read Garbage value when passed float values to the function accepting integer parameters answers. My question goes a bit deeper. I could have also asked there had I more than 50 reputation point. I am adding my code for more clarification:
#include <stdio.h>
#include <string.h>
void p2(unsigned int tmp)
{
printf("From p2: \n");
printf("tmp = %d ,In hex tmp = %x\n", tmp, tmp);
}
int main()
{
float fvar = 45.65;
p1(fvar);
p2(fvar);
printf("From main:\n");
printf("sizeof(int) = %lu, sizeof(float) = %lu\n", sizeof(int),
sizeof(float));
unsigned int ui;
memcpy(&ui, &fvar, sizeof(fvar));
printf("fvar = %x\n", ui);
return 0;
}
void p1(unsigned int tmp)
{
printf("From p1: \n");
printf("tmp = %d ,In hex tmp = %x\n", tmp, tmp);
}
The output is:
From p1:
tmp = 1 ,In hex tmp = 1
From p2:
tmp = 45 ,In hex tmp = 2d
From main:
sizeof(int) = 4, sizeof(float) = 4
fvar = 4236999a8
Passing a float value to a function that is declared beforehand (i.e. p2) with int arguments gives the correct result. When trying the same with a function that is not declared beforehand (i.e. p1) gives incorrect values. And I know the reason that compiler won't assume any type or arity of arguments for the function not declared before handed. That's why float value does not get typecasted to int in the case of p2.
My confusion is, in the case of p2, how exactly does float value get copied to local int variable tmp.
If it is 'bit by bit copy' than reading those locations should yield something (except 1) in hex at least (if not in integer). But that does not sound the case as output shows. I know that float representation is different.
And how p2 may read registers/stack locations that floats weren't copied to? as simonc suggested in the linked question?
I have included the size of int and float both and my compiler is gcc if that helps.
The C programming language is essentially a single-scan language - a compiler doesn't need to reread the code but it can assemble it line by line, retaining information only on how identifiers were declared.
The C89 standard had the concept of implicit declaration. In absence of a declaration, the function p1 is declared implicitly as int p1(); i.e. a function that returns an int and takes unspecified arguments that go through default argument promotions. When you call such a function giving it a float as an argument, the float argument is promoted to a double, as called for by default argument promotions. It would be fine if the function was int p1(double arg); but the expected argument type is unsigned int, and the return value is not compatible either (void vs int). This mismatch will cause the program to have undefined behaviour - there is no point in reasoning what is happening then. However, there are many old C programs that would fail to compile, if the compilers wouldn't support the archaic implicit declarations - thus you just need to consider all these warnings as errors.
Notice that if you change the return value of p1 into an int, you will get less warnings:
% gcc implicit.c
implicit.c:14:5: warning: implicit declaration of function ‘p1’ [-Wimplicit-function-declaration]
p1(fvar);
^~
But the observed behaviour on my compiler would be mostly the same.
Thus the presence of mere warning: implicit declaration of function ‘x’ is quite likely a serious error in newly written code.
Were the function declared before its use, as is case with p2, then the compiler knows that it expects an unsigned long as the argument, and returns void, and therefore it would know to generate correct conversion code from float to unsigned long for the argument.
The C99 and C11 do not allow implicit function declarations in strictly-conforming programs - but they also do not require a conforming compiler to reject them either. C11 says:
An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator).
and a footnote noting that
Thus, an undeclared identifier is a violation of the syntax.
However, it doesn't require a compiler to reject them.
This,
void p1(unsigned int tmp);
would be implicitly declared as
int p1();
by the compiler.
Although the compiler does not throw an error, it should be considered one as you can read in the linked post.
In any event, this is undefined behavior and you can't expect a predictable output.
In binary level, float and int don't look alike at all.
When trying to copy a float into a int, there's an implicit conversion, that's why when you call a function that takes int as argument but you provide a float you get the integer part of it, but in the final test you get to see how ugly it really look like. That's no garbage, that's how a float looks like in memory if you'd print it in hexadecimal. See IEEE 754 for details.
The issue with p1() however is that you are trying to call a function that has not been declared, so it's automatically declared as int p1(). Even though you later define it as void p1(unsigned int tmp), it has already been declared as int p1() (not taking any parameters) so it doesn't work (behavior is undefined). I'm pretty sure the compiler is screaming with warnings and errors about that, those errors aren't meant to be ignored.
Notice there's a big difference between declaring and defining a function. It is perfectly legal to define a function later, the way you are doing, but if you want it to work properly it has to be declared before any attempt to use it.
Example:
// declare functions
void p1(unsigned int tmp);
void p2(unsigned int tmp);
// use functions
int main()
{
p1(1);
p2(1);
}
// define functions
void p1(unsigned int tmp)
{
// do stuff
}
void p2(unsigned int tmp)
{
// do stuff
}

Is it possible to access function parameters after returning from a function? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Is there any way that I can access function parameters after returning from the function (i.e. in the calling function)?
Example:
void add (float a , float b) {
int c;
c=a+b;
return c;
}
void main () {
add (3,4);
if (a <4 && b<3) // a and b are variable in add functions
printf("a is 4 and b is 3");
}
Once execution leaves the function, parameters are no longer accessible. You'll need to store them temporarily in the calling function to be able to access them again:
int main ()
{
float a = 3.0f, b = 4.0f;
add (a, b);
if (fabs(a - 4.0f) < 0.005f && fabs(b - 3.0f) < 0.005f) // a and b are now local variables
printf("a is 4 and b is 3");
}
See Scope vs. Lifetime of Variable for more information.
A few other things:
The return type of main should be int.
You're checking for a < 4 && b < 3 to see if a is equal to 4 and b is equal to 3, which isn't right.
You should get in the habit of not checking floating-point values for equality. Better to check if they're near each other.
Your add function should have a non-void return type, probably float. (Hat tip: #ajp15243)
Although not illegal, it's normal to use the return value of a function somehow.
Local variables a and b are destroyed when you exit the function, so - no, you cannot do this.
Also, you defined add as void, while it should be int (because it obviously returns c).
You can have functions return variables, you just got to change the word "void" to the variable you want to return. So for your case:
void add (float a, float b)
Will be
int add (float a, float b)
Since it looks like you want to return an int variable, but I think it would be better if you just have the return variable be a float.
No.
You need to understand scope and storage.
Scope of a variable defined in a function is restricted to that function.
Variable declared in a function is stored on a stack frame corresponding to the function call, and all these variables are destroyed as the function returns.
Im not a C programmer but regardless of the language I think your current efforts are a little misguided. Dont get too caught up on what language youre using focus on writing well structured code because many concepts transcend the specific language. Most languages today are considered "Turning Complete" basically means what you can write in one you can write in another.
With that being said you have an add function that takes two arguments and then adds those two arguments and returns the value. Those arguments thatyou are passing are scoped within the add function block. And they are only reference for the parameters that you pass in when you actually call the function like you did add(4, 3).
So you can move your if conditional statement within you add function cause like I said when you call your add function the arguments will then have value and you can check it.
That is why you are able to say a + b. Cause when you call add those variables are what you pass into the function. Hope this makes sense. Happy coding!
is there any way that I can use the values of the variables that are defined in function to be call in a program
No, Not the way you have it written
Would it not be more meaningful if your existing code (in original post) were modified in the following ways:
1) Return type must be float for add() function
2) In main(), there is no reason to test a and b, they are not in scope outside of add() function.
3) Use results of add() function in a printf statement to see results.
4) Not an absolute requirement, but recommended that minimum prototype for main() be int main(void)
5) IF you had created a copy of floats somewhere outside of any function, toward the top of the file, then their scope would have allowed you to use them in main(). But it is not good practice to create global variables having the same name as argument names used in functions within the same file.
(see in-line comments for explanations)
float add (float a , float b) {//must return float, you already have a return statement
float c;//from int to float (because that matches the argument types being evaluated)
c=a+b;
return c;
}
float x = 5.0; //these are variables with global scope, meaning they exist and can be used in every function
float y = 7.2;
int main (void) {//change from void main() to int main(void)
float z=0;
z = x + y;//legal statement summing globals x & y and storing in local z
//add (3,4);//used in printf below
//if (a <4 && b<3) // a and b are variable in add functions (this is meaningless in context of an add function
//call the add() function, with float arguments, from here, and print out the results in one step.
printf("results of add are: %f", add(3.0,4.0));//change from 3 to 3.0 (just to be anal)
}

Is passing additional parameters through function pointer legal/defined in C? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Casting a function pointer to another type
Assume i initialize a function pointer with a function that actually takes less parameters then the function pointer definition, will the function still perform correctly if called through the function pointer?
I tried this with gcc and it worked as expected, but i wonder if that behaviour is consistent across compilers/platforms (i suspect in some enviroments it might wreak havoc on the stack):
#include <stdio.h>
typedef void (*myfun)(int, int, int);
void test_a(int x, int y, int z) {
printf("test_a %d %d %d\n", x, y, z);
}
void test_b(int x, int y) {
printf("test_b %d %d\n", x, y);
}
int main() {
myfun fp;
fp = test_a;
fp(1, 2, 3);
fp = (myfun) test_b;
fp(4, 5, 6);
}
It is undefined behavior. Use at your own risk. It has been rumored to cause Nasal Demons!
The behavior of your program is undefined. The fact that it compiles at all is because of the cast, which effectively tells the compiler "this is wrong, but do it anyway". If you remove the cast, you'll get the appropriate error message:
a.c:17:8: error: assignment from incompatible pointer type [-Werror]
(From gcc -Wall -Werror.)
More specifically, the behavior depends on the calling conventions. If you were on a platform were the arguments were passed in "reverse" order on the stack, the program would give a very different result.
The function call is undefined behavior.
(C99, 6.3.2.3p8) "[...] If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined."
For information note that a function type:
(C99, 6.2.5p20) "[...] describes a function with specified return type. A function type is
characterized by its return type and the number and types of its parameters."
Whether it works will depend on the calling convention being used.
I wouldn't recommend it.

Resources