Content of X.c:
int i;
main ()
{
fun ();
}
Content of Y.c:
int i;
fun ()
{
}
Why does these two files compile with no error ? (using GCC)
But if i use int i = 10; it prints a multiple definition error.
You may be interested in this question and the answers. Keywords: "tentative definition".
Tentative definitions in C99 and linking
Assuming you really want an independent variable called i in each of these two files, you need to prefix them with static in order to give them internal linkage.
static int i = 10;
If you want i to be the same variable in both files, so changes in one affect the other, use the answers you were given 3 hours ago when you asked a variant of the question. If it is to be shared, you need to define the variable in one place.
As to why it didn't cause an error without the init, I think that's because you weren't using the variable until it needed initializing and so the compiler ignored it.
Because there is a difference between a declaration and a definition. int i; does nothing more than introducing a name. int i = 10; on the other hand defines i, hence, a place in the memory must be reserved to store the value it corresponds to. But it is impossible for the compiler to know which value corresponds to i as you want to associate two memory locations with the name i.
This is under the assumption that you link these files against eachother, which is not entirely clear from your explanation.
Related
I saw the link http://www.cs.uregina.ca/Links/class-info/cplusplus/Standards/Disk10/aliasing_c.html about aliasing in c. The program there is shown below.
/********************************
An example of aliasing in C.
Output:
3
3
********************************/
#include < stdio.h >
int main()
{
int G_Var = 2;
/* call SomeFunction with the Global Variable as a parameter */
SomeFunction(G_Var);
return 0;
}
/* InputVar becomes an alias fo G_Var */
void SomeFunction(int &InputVar)
{
int G_Var;
int InputVar;
/* Global Variable is set to new value */
G_Var = InputVar + 1;
/* Equivalent to G_Var = G_Var + 1 */
printf("%i\n", InputVar);
printf("%i\n", G_Var);
}
Is the code correct and is working according to what is commented in the code?
Whoever wrote the link was severely incompetent and shouldn't be teaching C. They should rather enlist in a beginner's class themselves.
int G_Var = 2; is not a global variable, it is a local one with automatic storage duration. Both the one in main() and the one inside the function.
The code posted is C++, not C. C does not have references.
The term alias/aliasing refers to when several pointers (or C++ references) may be assumed to point at the same memory location.
int InputVar; in the function conflicts with the parameter name so the code doesn't make any sense. In case there were no name conflict, the variable would be uninitialized and then used, which would be senseless.
Is the code correct and is working according to what is commented in the code?
Whoever wrote this example was so confused that it's really hard to be telling what they are trying to teach, or in which language for that matter. The code does not compile for multiple fundamental reasons. Just forget about this mess.
Four things to say:
C does not have C++-kind of aliases/references. It is a C++ feature only.
So,
/* InputVar becomes an alias fo G_Var */
void SomeFunction(int &InputVar)
is wrong.
G_Var is not a global variable. You declare it two times to be local to main and SomeFunction. If you want to declare G_Var as global variable it has to be declared once at global scope, not inside of a function, and only access it by its name, not declaring its type twice.
But beside that the use of global variables is deprecated. Rather use parameter passing.
SomeFunction() isn't declared before the call to it in main(). Usually this would give you a diagnostic as the compiler don't know what SomeFunction() is.
InputVar is used as reference parameter, but also declared twice in SomeFunction. Here is a conflict.
I guess you never compiled this code before asking, which is a fault. It would have answered many questions of yours including the main one.
"Is the illustration on Aliasing in C correct?"
"Is the code correct and is working according to what is commented in the code?"
No, it isn't. The whole code is defective.
It gives the impression that the authors didn't knew how to either write correct C nor C++ code.
I am reading the book "Programming in C" and found in Chapter 10 an example like this:
#include <stdio.h>
void test (int *int_pointer)
{
*int_pointer = 100;
}
int main (void)
{
void test (int *int_pointer);
int i = 50, *p = &i;
printf ("Before the call to test i = %i\n", i);
test (p);
printf ("After the call to test i = %i\n", i);
return 0;
}
I understand the example, but I don't understand the line void test (int *int_pointer); inside of main. Why do I define the signature of test again? Is that idiomatic C?
It's definitely not idiomatic C, despite being fully valid (multiple declarations are okay, multiple definitions are not). It's unnecessary, so the code will still work perfectly without it.
If at all, perhaps the author meant to do
void test (int *int_pointer);
int main (void) {
...
}
in case the function definition was put after main ().
void test (int *int_pointer); is just a declaration (or prototype) of function test. No need of this declaration in main because you already have function definition before main.
If the definition of test were after main then it would be worth of putting its declaration there to let the compiler know about the return type, number of arguments and arguments types of test before calling it.
It's not idomatic C, but still valid.
The line is a declaration of the function test, not definition. A function can't be defined multiple times, but it's valid to have multiple declarations.
It is perfectly idiomatic C, and it actually has a (limited) practical use - although not one that is demonstrated by this example.
When you declare a function or other name at the usual global level, it is brought into scope for all function bodies in the code following the declaration. A declaration cannot be removed from a scope once it has been introduced. The function is permanently visible to the rest of the translation unit.
When you declare a function or other name within a braced block, the scope of the declaration is limited to that block. Declaring a function within the scope of another function will limit its visibility, and not pollute the global namespace or make it visible to any other functions defined in the same translation unit.
This is meaningless in the case of the example, because the definition of test also brings it into scope for all following bodies - but if test were defined in another translation unit, or even if it were defined only at the very bottom of this TU, hiding the declaration inside main would protect any other functions defined afterwards from being able to see its name in their scope.
In practical terms this is of limited use - normally if you don't want a function to be visible, you put it in another translation unit (and preferably make it static) - but you can probably contrive a situation where you might want to use this ability for constructing a module-loading system that doesn't export the original declarations of its components, or something like that (and the fact that this doesn't rely on static/separate object files might potentially have some relevance to embedded/non-hosted target environments where the linking step might not work as it does on PC, allowing you to achieve a measure of namespace protection in a purely-#include-based build system).
Example:
struct module {
void * (* alloc)(size_t);
void (* dealloc)(void *);
} loaded_module;
int main(void) {
if (USE_GC) { // dynamically choose the allocator system
void * private_malloc_gc(size_t);
void private_free_noop(void *);
loaded_module = (struct module){ private_malloc_gc, private_free_noop };
} else {
void * private_malloc(size_t);
void private_free(void *);
loaded_module = (struct module){ private_malloc, private_free };
}
do_stuff();
//...
}
// cannot accidentally bypass the module and manually use the wrong dealloc
void do_stuff(void) {
int * nums = module.alloc(sizeof(int) * 32)
//...
module.dealloc(nums);
}
#include "allocator_implementations.c"
It's not idiomatic; you typically see it in code that has problems getting their header files in order.
Any function is either used in one file only, or it is used in multiple files. If it is only used in its own file, it should be static. If it is used in multiple files, its declaration should be in a header file, and anyone using it should include the header file.
What you see here is very bad style (the function should either be static, or the declaration should be taken from a header style), and also quite pointless because the compiler can see the declaration already. Since the function is in the same file, it's not dangerous; if the declaration and function don't match the compiler will tell you. I have often seen this kind of thing when the function was in a different file; that is dangerous. If someone changes the function, the program is likely to crash or misbehave.
I have read this exam code.
"a.c":
int global_1 = 100;
"b.c":
extern int global_1;
int global_2 = global_1 * 2;
int main()
{
return 0;
}
gcc give “error: initializer element is not constant"
I do not write this code, but I want to know why and how to fix.
Thanks.
The problem you are facing is that in order to initialise a variable (global_2 here) it's value (or all values of what it depends on, in your case global_1) need to be known.
When you initialise a variable in a function then it's value only needs to be known at runtime and that is generally the case or you will get an undefined symbol error during compile or link time.
Globals need to be initialised by the compiler during compile time.
extern int global_1;
Says to the compiler that global_1 exists, but not in this compilation unit. It will be accessible after linking. You can use it in functions, but the linker needs to link it first with an object file that actually contains it.
Thus the compiler is unable to initialise it at compile time resulting in the error you see. Linking comes after compiling.
If you need to initialise globals that reference globals in a different compilation unit then you will need to do this in a function. For example the first stem in main().
The error says it all: Initialisers need to be constants.
To fix this you might like to modify your code like this:
int global_2 = 0;
int main()
{
global_2 = global_1 * 2;
I was working on some C-output questions and found the following code:
http://ideone.com/O0tQnr
In this code , as one can see , inside main , a static variable having same name has been declared. For this I searched on Stack-Overflow and found
How are static variables with the same name in different functions identified by the System?
The answers given for this question suggest different approaches viz.
The names of static variables are usually included within the debugging symbol table.
some embedded ones (compilers) simply add a number to the end of each duplicate name
They are likely mangled in the table.
I wanted to know how are static variables actually implemented in C, as all answers are suggesting something different?
Also to check whether this was only a one-off chance I also ran the code:
http://ideone.com/zpRVCa
but the error:
prog.c:5:21: error: called object ‘GetSize’ is not a function or function pointer
int myvar=GetSize(GetSize);
^
prog.c:4:11: note: declared here
static GetSize;
^
indicates that the compiler found a conflicting declaration / redeclared Getsize.
Different entities may have the same identifier if they have different scopes or are in different name spaces1. In the case of int main() { static int main; … }, the first main has file scope, and the second main has block scope.
At any particular point, only one identifier is visible in a name space. In GetSize(GetSize), only the static GetSize is visible. It hides the int GetSize(int), so the function GetSize is not visible. Thus, this code gets an error.
An identifier declared at file scope with static has internal linkage. An object identifier declared at block scope without extern (including those that have static) has no linkage. Because these identifiers do not have external linkage, they never need to be known outside the current translation unit. Therefore, these identifiers do not need to appear in object files: There is no need for them to have names visible to the linker. They are typically accessed by code generated by the compiler during compilation of the translation unit, and this code addresses objects numerically (by location in memory), not by name.
Many C implementations provide debugging facilities. Debuggers generally need to know the names of things even if they have internal or no linkage. In these cases, the C implementation may use any scheme it desires to record information about names.
1 The name spaces of C are: label names; tags of structures, unions and enumerations; members of structures or unions (a separate space for each structure or union); and all other identifiers. The standard also refers to a name space for macro names.
The two cases you are describing have a fundamental difference. In the first case:
int main(){
static main;
int myvar=GetSize(main);
printf("%d",myvar);
return 0;
}
Here, you are inside the function main and declaring a static integer also called main. The function main is called from an external place which knows about main as a function and calls it as such. Inside the definition of main above, you have redefined main as the static integer, then calling GetSize(main) doesn't cause an error because it complies with the definition of GetSize.
In the second case:
int GetSize(int);
int main(){
static GetSize;
int myvar=GetSize(GetSize);
printf("%d",myvar);
return 0;
}
Here you've redefined GetSize to be a static integer, but then attempted to call GetSize as if it were a function. So you have a direct conflict in terms of the definition (static integer) and how you are using it (a function).
There's a clue in the error message: "not a function or function pointer". The compiler can't assume that the name to the left of the ( is a function name, because any expression yielding a function pointer is also allowed there, including a variable declared as a function pointer.
At the parsing stage, there's no type checking to help find the right variable. Here's a program that doesn't work for a similar reason:
int main(void)
{
struct { int x,y; } s = {0,0};
{
int s;
printf("%d\n", s.x);
}
}
The outer s is capable of fitting into the expression s.x, but the inner s is the one that is visible.
And here's a program that works because the outer-scoped function is not preferred over the inner-scoped variable, which happens to be a function pointer capable of being called with itself as an argument:
#include <stdio.h>
#include <stdlib.h>
void func()
{
puts("Everything's fine.");
}
void fp()
{
/* This won't happen. */
abort();
}
int main(void)
{
void (*fp)() = func;
fp(fp);
}
I've faced three separate situations in C lately that I would assistance on:
My C code has a global variable:
int ref_buf; //declared in a header file
In a function definition I use the same name as a parameter:
void fun(int ref_buf, param2, param3)
{
}
Will it overwrite the originally defined global variable and will it cause bugs?
Can I declare a static variable in a C data structure like so?:
struct my
{
int a;
static int b;
};
Does it work? Is there any specific situation where one would need it?
Can I initialize a individual structure variable as follows:
struct my
{
int a;
int b = 4;
};
Question 1
All references to ref_buf in that function will bind to the parameter and not the global variable.
Question 2
This is not legal in C but is legal in C++. The keyword static in C can only be used on file scope variables or on locals.
Question 3
No this is not legal in C (or C++). You will need to create a factory method to handle this.
my create_my() {
my m;
m.b = 4;
return m;
}
On Q3: GCC allows you to initialize a struct like this (as required by the C99 standard):
struct
{
int a;
int b;
} my = { .b = 4 };
GCC doc on designated initializers
1a) The local and global variables are separate entities, and so the local one won't overwrite the global. However, the global one won't be accessible inside the function (see also notes below).
1b) It not actually incorrect, but it is guaranteed to cause confusion, and confusion causes bugs, so it's best to use different names for each.
2) No, that's not legal C. You can however make the whole struct static.
3) No. You do it like this:
struct my
{
int a;
int b;
} = {0, 4};
Note 1: Variables should be declared in .c files, not .h files. If you need to make a variable accessible in multiple files, put an extern declaration in the header file.
Note 2: Avoid global variables if at all possible.
Question 1:
I think the variable declared in the local scope takes precidence, it shouldn't overwrite it but in the scope that the variable is declared it will be used instead.
That is assuming that it compiles.
On Q1:
Do not declare variables in a header file. If you include that header file in two source files and compile the source files together, you've got problems. Maybe your linker will get you out of them, maybe not.
If you really need global variables, and this happens a lot less than typical beginners think, put something like extern int ref_buf; in the header file, and int ref_buf; in a source file. That means there is one ref_buf, and all other source files will be able to find it.
The function parameter is essentially a new variable with the same name, and all references in the function will be to it. You will not be able to access the global variable from within that function. The function creates an inner scope, and variables declared in an inner scope are different from those in an outer one. This is potentially confusing, and makes it easy to create bugs, so having variables of the same name and different scopes is generally discouraged. (Variables of the same name in different struct definitions are usually not confusing, since you have to specify what struct contains the variable.)
The compiler will compile the function, but a good compiler will issue a warning message. If it refuses to compile because of one variable shadowing another of the same name, it isn't a real C compiler.
1) Local variables always take precedence e.g.
int ref = 10;
void fun(int ref)
{
printf("\n%d\n", ref);
}
int main()
{
fun(252);
return 0;
}
shows: 252
Qs 2 and 3 won't work in C.
Yes, it will technically overwrite, but a good compiler will warn you about this situation, and you will have "warnings = errors" on when you compile, so this won't actually compile.
Not needed, since the "my" struct is already declared as static, and it is therefore declared for the entire struct. This allocates the memory for the entire struct, so there is no need to say "take part of the struct which is already static and make it static".
No, not in the definition, but you can when you create an "instance", something like:
struct my MY =
{
{0, 4}
};