I am calling one function in which values are printed, but when void is added before the call, the function is not giving correct (or any) output.
I tried various methods
#include <stdio.h>
void func1();
void func2();
void func1()
{
printf("Inside func1()\n");
}
void func2()
{
printf("Inside func2()\n");
}
int main()
{
void func1();
void func2();
printf("Inside main()\n");
return 0;
}
Output is :-
Inside main
When void is removed before calling func1 and func2, the output is changed.
#include <stdio.h>
void func1();
void func2();
void func1()
{
printf("Inside func1()\n");
}
void func2()
{
printf("Inside func2()\n");
}
int main()
{
func1();
func2();
printf("Inside main()\n");
return 0;
}
Output is :-
Inside func1
Inside func2
Inside main
Can anyone explain how void is affecting desired output?
The statement void func1(); within main is a function declaration. This is a no-op at runtime.
func1(); actually calls the function.
It's how the language grammar works, that's all. It's rather clever if you think about it.
In this case, void func1(); is not a call to the function, it just means: somewhere there may be a function with this signature, I want to use it even if it is not declared forward. Usually we call this a function declaration and we don't use it inside main but at the beginning of the file.
A function declaration is the action to tells the compiler about a function's name, return type, and parameters.
eg:-void func1();
A function definition provides the actual body of the function.
eg:-
void func1()
{
printf("Inside func1()\n");
}
To call a function, you simply need to pass the required parameters along with the function name, and if the function returns a value, then you can store the returned value.
eg:-func1();
A declaration always begins with a type name. When you write
int func();
you are declaring to the compiler that you have a function that takes an unspecified number of parameters and returns int (so the compiler knows about it).
When you write
func();
you are telling the compiler to execute function func(); and discard its result, in a normal execution statement.
Always you have a C statement beginning with a type identifier
, that's not to be executed, but to inform the compiler of the existence of such thing (to declare it)
In your example, you changed two declarations at the beginning of main() into to execution statements. As such, the compiler generated code to execute those, resulting in the output you got on execution.
Related
This question already has answers here:
Error "initializer element is not constant" when trying to initialize variable with const
(8 answers)
Closed 2 years ago.
Hi i have a test code for calling malloc as below:
#include <stdio.h>
#include <stdlib.h>
int *p;// = (int*)malloc(sizeof(int));
int main() {
//...
}
Of course this code will be fail when compile with the error: initializer element is not constant and i have referenced this question: Malloc function (dynamic memory allocation) resulting in an error when it is used globally. They said that we have to use malloc() in side a function. But if i change my code to:
#include <stdio.h>
#include <stdlib.h>
int *p;
static int inline test_inline(int *x) {
printf("in inline function \n");
x = (int*)malloc(sizeof(int));
return x;
}
test_inline(p);
int main(){
//...
}
As the definition of inline function: "Inline Function are those function whose definitions are small and be substituted at the place where its function call is happened. Function substitution is totally compiler choice." So this mean we can substitute the inline function test_inline in above example with the code inside it and it means we have call malloc() in global ? Question 1: is this wrong about inline or malloc() ?
Question 2: In the link i give about malloc function dynamic there is an answer said that "Not only malloc, u can't call any function as you have called here. you can only declare function as global or local there" but i see that we still can call function in global and in global we can initialization not only declaration as below:
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1;
int test() {
printf("hello");
}
test();
int main() {
//...
}
So this mean in the global we still can declaration and initialization and call function. But when we compile the above code it has a warning that warning: data definition has no type or storage class So why we have this warning with variable b ? I do not see any thing which inconsequential here. And with the line test(); i have call a function outside main(), i know this make no sense because we never run test() but i have no problem, stil build success. So back to question 1 about the malloc(), i think with the answer that "we can not call a function in global or can not initialize", i think it is not true. Is there any explain more reasonable?
Please refer to the comments.
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1; //this is only allowed, because the previous line is a tentative definition. [1]
int test() {
printf("hello");
}
test(); // this is taken as a function declaration, not a function call [2]
int main() {
//...
}
Case [1]:
Change you code to
int b = 5; // not a tentative defintion.
b = 1; // this assignment is not valid in file scope.
you'll see an error.
Case [2]:
If the signature of the function differs, you'll again see an error. Example: try the below:
float test( int x ) {
printf("hello");
return 0.5;
} //return changed to float, accepts an int as paramater.
test(); //defaults to int and no parameter - conflict!!
this will produce the error for conflicting types.
So, bottom line, no assignment, function call - all in all, no code that needs to execute at runtime, can be put into file scope. The reason behind that being, unless it's contained in a function that's called from main(), there's no way to know when / how to execute it.
You're not calling functions "globally".
Taking your example:
#include <stdio.h>
#include <stdlib.h>
int b;
b = 1;
int test() {
printf("hello");
}
test();
int main() {
//...
}
In C types default to int.
So the lines
int b;
b = 1;
are basically
int b;
int b = 1;
and the lines
int test() {
printf("hello");
}
test();
are just
int test() {
printf("hello");
}
int test(); // -> this is just a matching declaration
Have a look at:
https://godbolt.org/z/3UMQAr
(try changing int test() { ... to char test() { ... and you get a compiler error telling you that those types don't match)
That said, you can't call functions there. Functions are called at runtime by your program (especially malloc, which is asking your OS to allocate memory for you). I'm not a C expert here but as far as I know C doesn't have constexpr functions, which would be the only "exception".
See: Compile-Time Function Execution
Question 1: is this wrong about inline or malloc()
kind of: malloc does have to be called in a function, but the variable it works on can be declared global. i.e. int *pointer = NULL;//global scope
then pointer = malloc(someByteCount);//called within function. Now, pointer is still global, but also has a memory address pointing to someByteCount bytes of memory.
Question 2: In C, all functions are defined on the same level of a .c file, just like main(void){...return 0}, but all functions (except main(void)) must be called within the {...} of other functions, so in short, functions cannot be called from global space.
Illustration for Q2:
//prototypes
void func1(void);
void func2(void);
void func3(void);
int main(){
int val = test_inline(p);//...
}
int main(void)
{
//legal
func1();
func2();
func3();
return 0;
}
//not legal
func1();
func2();
func3();
//definitions
void func1(void)
{
return 0;
}
void func2(void)
{
return 0;
}
void func3(void)
{
return 0;
}
Errors in syntax of your example (see comments):
int *p = NULL;//initialize before use
static int inline test_inline(int *x) {
printf("in inline function \n");
x = (int*)malloc(sizeof(int));
printf("%p\n", x);
return 0;
//return x;//function returns int, not int *
}
//... test_inline(p);//must be called in a function
int main(void){
int val = test_inline(p);//function declaration returns int, not pointer
return 0;
}
This code compiles, and runs, but as noted in comments, usefulness may be lacking.
Question 1: is this wrong about inline or malloc() ?
Neither. Your understanding of inline is incorrect. The function call may be replaced with an inline expansion of the function definition. First, let's fix the function definition because the return type int doesn't match the type of what you're actually returning:
static inline int *test_inline( int *x )
{
printf( "in inline function\n" );
x = malloc( sizeof *x );
return x; // x has type int *, so the return type of the function needs to be int *
}
If you call this function like so:
int main( void )
{
int *foo = test_inline( foo );
...
}
what the compiler may do is substitute the function call with the assembly language equivalent of the following:
int main( void )
{
int *foo;
do
{
printf( "in inline function\n" );
int *x = malloc( sizeof *x );
foo = x;
} while( 0 );
...
}
Nothing's happening "globally" here. The substitution is at the point of execution (within the body of the main function), not at the point of definition.
Question 2: In the link i give about malloc function dynamic there is an answer said that "Not only malloc, u can't call any function as you have called here. you can only declare function as global or local there" but i see that we still can call function in global and in global we can initialization not only declaration as below:
In the code
int test() {
printf("hello");
}
test();
the line test(); is not a function call - it's a (redundant and unnecessary) declaration. It does not execute the function.
Here are some excerpts from the language definition to clarify some of this:
6.2.4 Storage durations of objects
...
3 An object whose identifier is declared without the storage-class specifier
_Thread_local, and either with external or internal linkage or with the storage-class
specifier static, has static storage duration. Its lifetime is the entire execution of the
program and its stored value is initialized only once, prior to program startup.
Bold added. Any variable declared outside the body of a function (such as p in your first code snippet) has static storage duration. Since such objects are initialized before runtime, they cannot be initialized with a runtime value (such as the result of a function call).
6.7.4 Function specifiers
...
6 A function declared with an inline function specifier is an inline function. Making a
function an inline function suggests that calls to the function be as fast as possible.138)
The extent to which such suggestions are effective is implementation-defined.139)
138) By using, for example, an alternative to the usual function call mechanism, such as ‘‘inline
substitution’’. Inline substitution is not textual substitution, nor does it create a new function.
Therefore, for example, the expansion of a macro used within the body of the function uses the
definition it had at the point the function body appears, and not where the function is called; and
identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a
single address, regardless of the number of inline definitions that occur in addition to the external
definition.
139) For example, an implementation might never perform inline substitution, or might only perform inline
substitutions to calls in the scope of an inline declaration
All this means is that the inlined code behaves like it was still a single function definition, even if it's expanded in multiple places throughout the program.
I have done this quiz, and do not understand the output
#include <stdio.h>
int main()
{
void demo();
void (*fun)();
fun = demo;
(*fun)();
fun();
return 0;
}
void demo()
{
printf("GeeksQuiz ");
}
Expected: Compiler error because I thought that normally demo() would need to be initialized before the call in main()?
Actual results: GeeksQuiz GeeksQuiz
Is my assumption wrong that functions generally need to be defined before they can be called?
functions generally need to be defined before they can be called
Well, not actually, compiler just needs to see a prototype before the call (usage). A forward declaration would be enough.
In your case, inside main(),
void demo();
is serving that purpose. Note that, this is not a function call.
In C, is there a way to ensure a function is called only once without using pthread_once?
The following works in C++ but apparently not in C because initialization of a static variable must be to a constant (as I interpret the compile error)
// main.c
int func()
{
return 42;
}
int main( int argc, char* argv[] )
{
static int i = func();
return 0;
}
I thought using the comma operator might get around this, but that doesn't work either:
// main.c
int func()
{
return 42;
}
int main( int argc, char* argv[] )
{
static int i = ( func(), 42 );
return 0;
}
Compilation of both results in the following compile error:
> gcc -g main.c
main.c: In function 'main':
main.c:10:18: error: initializer element is not constant
Are there any ways to circumvent this and ensure a function is only invoked once (from a calling function scope) without using pthread_once?
To be specific, I don't want to return early from func() if it has been called once, I'm interested in compile-time assurance that func() is only called once from a calling function scope - i.e. similar to how C++ would handle the above code.
(In other words, the above code is legal to a C++ compiler, which ensures func() is only called once - is there an equivalent way to do this in C without pthread_once?)
EDIT:
I didn't phrase this ideally in the original post: I was looking for a solution that didn't involve wrapper/helper functions or variables; i.e. I was curious to know if there was a construct in the C language that allowed this situation to be handled equivalently to how it is handled in C++. jxh's solution fits that best, making use of a gcc extension.
No way to leverage static variable initialization
Your attempt to leverage static variable initialization will not work. C only allows static variable to be initialized with constants, so a function call is out.
One shot call of a function at program start (or library load)
It is not clear why you want the onetime call, but if it's okay to do it at program startup, there is a GCC specific solution.
You can assign the constructor attribute to the function.
#include <stdio.h>
__attribute__((constructor))
void func()
{
puts(__func__);
}
int main () {}
This suggestion does not perform your specific ask:
I'm interested in compile-time assurance that func() is only called once from a calling function scope ...
Instead, it assures the function is called exactly once when the program starts (or when the library it is a part of is loaded).
Use a static variable as a guard
If you need to control when the function is called in the exact way initialization of a static variable local to a function is initialized, then you could use a static variable to track whether your one shot function has been called yet with its own static variable. Other answers have already described how to accomplish this, but for completeness:
void caller_of_func()
{
static bool func_already_called;
if (!func_already_called) {
func();
func_already_called = true;
}
/*...*/
}
Use a function pointer!
Another way to accomplish your goal would be to call the function through a function pointer. The initial call to the function would do the real work, and then switch the function pointer to point to a function that does nothing.
void nothing_func(int *x);
void initial_func(int *x);
void (*func)(int *x) = initial_func;
void initial_func(int *x) {
*x = 42;
puts(__func__);
func = nothing_func;
}
void nothing_func(int *x) {
puts(__func__);
}
void foo(void) {
static int x;
func(&x);
printf("%s: %d\n", __func__, x);
++x;
}
int main(void) {
foo();
foo();
}
You can wrap your function in another function which checks a static variable and calls func only if it hasn't been called before as -
static int func_internal() {
...
}
int func() {
static int guard = 0;
if (guard)
return 0;
guard = 1;
return func();
}
Now, expose only func to other modules.
You can do this with a static flag.
// main.c
int func()
{
return 42;
}
int main( int argc, char* argv[] )
{
static int initialized = 0;
if(!initialized) {
func();
initialized = 1;
}
}
The first time through the calling code, the initialized flag is unset, so the function will be run. For any subsequent calls, the flag is already set and so the function will not be called.
In the following code, get_func_name() can be a system call, a library call, or a function defined my myself. Without taking any parameter, how can I let get_func_name() print out the name of the calling function, without using the information from the stack?
Also, besides the name of the caller, can I print out anything in get_func_name() that can uniquely identify the caller?
void get_func_name(){
/*What magic goes here?*/
}
void func2(){
func3();
get_func_name(); /*Should print out "func2()"*/
}
void func1(){
func2();
get_func_name(); /*Should print out "func1()"*/
}
void main(){
func1();
get_func_name(); /*Should print out "main()"*/
}
It depends on your scenario.
You could consider the pre-defined identifier __func__. The standard says:
The identifier __func__ shall be implicitly declared by the translator as if,
immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function.....
EXAMPLE Consider the code fragment:
#include <stdio.h>
void myfunc(void)
{
printf("%s\n", __func__);
/* ... */
}
Each time the function is called, it will print to the standard output stream:
myfunc
You could somewhat mimic get_func_name with a macro like this:
#define print_func_name() { printf("%s\n", __func__); }
However if your task is different and you want the name of the caller in a general case, then I see no way to get it without checking the stack. (And even if you have access to the stack, you need some debug information to map the caller's address to caller's name.)
#include <stdio.h>
void m();
void n() {
m();
}
void main() {
void m() {
printf("hi");
}
}
On compiling, an error
"undefined reference to m"
is shown. Which m is being referred to?
First, let me declare clearly,
Nested functions are not standard C. They are supported as GCC extension.
OK, now, in your code, m() is a nested function inside main(). It is having block scope for main() only. Outside main() other functions cannot see the existence of m() ,neither can call m() directly. m() can be called only inside main().
In your case, the call to m() inside n() is causing the issue. Even if you provided the forward declaration as void m();, linker won't be able to find the definition of m() and throw error.
Solution: Move the definition of m() outside main(), then you can use it from any other function.
Also note, the recommended signature of main() is int main(void).
As has been explained elsewhere, C doesn't support nested functions as a rule (gcc does as an extension, but almost no other compiler that I know of does).
You need to move the definition of m outside of main. Preferably you should define m before it is used by n:
#include <stdio.h>
void m()
{
printf("hi\n");
}
void n()
{
m();
}
int main( void ) // void main() is not a valid signature for main
{
n(); // call n, which calls m, which prints "hi"
return 0;
}