C Global Variable Code giving an compilation error - c

So I'm new to c and wrote some code but i'm not sure why i'm getting an error when i try to run it.
int GlobalVariable=0;
int main()
{
int LocalVariable=0; //can be used within main()
dis();
printf(GlobalVariable);
return 1;
}
int dis()
{
GlobalVariable=5; //Can be accessed in any functions and made changes to it
}

Here is the prototype of printf function:
int printf(const char * restrict format, ...);
And look what you are typing:
int GlobalVariable=0;
printf(GlobalVariable);

The problem is that you used a function without first telling the compiler about it.
In this case you must provide function prototype as the function definition itself is provided after main
int dis( void ); // function prototype
int main()
{
...
}
int dis() // function definition
{
...
}
Alternatively, you can put the function definition before main(). But usually it would be better to have function prototypes before main() and (usually) even better to put the prototypes in a separate header file - that way it'd be easier to look straight into the main program without being bother about other function details.

Related

why can not malloc in global but can use inline function for malloc [duplicate]

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.

Why does the function call work even though it is not defined before the call?

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.

Declaring a function?

in C I am writing some of my very first exercises. Earlier on, I tried to declare a simple function inside of main and it comes with an error: "function definition is not allowed here". But I thought a function could be declared inside of main or outside, the only difference being the scope?? I have also read, in here, of other people writing functions inside of main, so why won't it let me do it?
thanks
You can declare a function inside another function:
int main(void) {
int foo(int); // declaration
...
}
But you can't define a function inside another function:
int main(void) {
// Doesn't work.
int foo(int x) {
return x * 2;
}
...
}
Also, declaring functions inside other functions is a really unusual thing to do, and essentially never necessary.

Why its returning an error?

#include <stdio.h>
int call()
{
extern int b;
b=10;
printf("%d",b);
}
int main ()
{
int b=8;
call();
return 0;
}
Why is throwing an error like these do I get the following linker error:
/tmp/ccAsFhWX.o:meka.c:(.text+0x7): undefined reference to `_b' collect2: ld returned 1 exit status
I wanted to change the b value in the other function using extern keyword but it gives me an error.am i right in doing so ?
Declaring the extern int b declares it as.... extern. It must be defined elsewhere. If it isn't, drop the extern keyword?
I think you wanted a global variable:
#include <stdio.h>
static int b;
int call()
{
b=10;
printf("%d",b);
}
int main ()
{
b=8;
call();
return 0;
}
If you declare the global b as extern you gain the possibility (and the duty) to define it elsewhere (perhaps in another translation unit (helpers.c) or a library (helpers.a) etc.)
In the C programming language, an external variable is a variable defined outside any function block. Please read about extern variables (here, for example).
Also, variables have scopes. For example, it can be a local variable, a global variable etc. You can read more about that here.
So what you have done here is declared a function scope variable in function call () without defining it using the power of extern keyword. In other words, simply tells the compiler that variable already exists somewhere. On top of that, you declared and defined another function scope variable in function main (), which has the same name. It is important to understand that those variables are totally different. So at the end of day, when you link your program, the definition of the variable b for function call () is not found. You declared it but never defined, remember?
Here are possible solutions. Do not declare multiple b variables as that was clearly not your intent. Stick with a single declaration and definition:
#include <stdio.h>
extern int b;
void call()
{
b = 10;
printf("%d\n",b);
}
int b = 8;
int main () {
call();
return 0;
}
But global variables are usually very bad - global scope makes them extremely pipeline unfriendly, introduce threading issues etc. So you must look into something like this:
#include <stdio.h>
void call (int *b)
{
printf ("%d\n", *b = 10);
}
int main () {
int b = 8;
call (&b);
return 0;
}
I'd also recommend you read the following question and answers here. It explains a lot about extern variables in C.
And by the way, you function call () is declared with int return type but returns nothing.
Hope it helps!
To change the "b" in main(), you must pass a pointer to "call" like call (&b) and then do
void call (int *b) {
*b = 10;
printf("%d",*b);
}

C Function Pointers - What happens when you drop an argument?

all. I'm currently working with an old established code base for a new project which is basically undocumented (i.e. averages 1 one-line comment per file). I just ran into something which I haven't seen before and am not quite sure how to interpret.
Firstly, they define a function type and a function in the header file (.h) in the form:
typedef void (*SOME_FUNCTION)(void *data, EXECUTION_CONTEXT *ec);
void add_function(SOME_FUNCTION aFunction, void *data);
In the main source file (.c), there is a function defined:
void add_function(void (*f)(void *data), void *data)
{
(Some code here)
}
So okay, there's a function pointer... but what the heck happened to the second argument, ec? Why would someone use a code design like this? For reference, when the function add_function is used, it is used in this sort of form:
void passedFunction(void *data, EXECUTION_CONTEXT *ec)
{
(Stuff the function does.)
}
void CallingFunction()
{
data = (some data stuff);
add_function((SOME_FUNCTION)passedFunction, data);
}
So, as you can see, the passed functions use the correct form that fits the original SOME_FUNCTION argument signature, but the definition for the add_function arguments is short by one argument.
Formally, the results are undefined: you are only permitted to call a function via a function pointer if the types match.
As for what actually happens, it depends on the calling convention and what the function does with the arguments. Chances are, the results aren't going to be good.
To add on James' answer:
Since the default calling convention is most likely cdecl, the call site is responsible for cleaning up the stack after passedFunction returns. Since the call site knows that it passed just 1 argument to the callee, the compiler can clean up the stack normally (even though technically this is undefined behavior).
Change the calling convention on passedFunction to stdcall though, and you 're in for some fireworks.
From the example code below, it doesn't appear that the variable(s) that are defined in the function pointer matters during the check. The code below compiles without warning.
#include <stdio.h>
int temp(int (*m)());
int main(int argc, char *argv[]) {
return temp(main);
}
int temp(int (*m)()) {
return 1;
}
However, the code below throws an error.
#include <stdio.h>
int temp(void (*m)());
int main(int argc, char *argv[]) {
return temp(main);
}
int temp(void (*m)()) {
return 1;
}
Due to this; it seems that the compiler (at least in my case GCC) only cares what the return value of the function pointer will be. The interesting thing here is that you CAN send the parameters correctly but if you do NOT specify the parameter (in our example m()), then the variables in m() when called will be junk.

Resources