Can i make extern variable const? - c++

I have a global variable which i want to share in the whole project.
// A.h
int a;
But i only write it in one place, and other place only need to read.
// B.h : only place can modify a
extern int a;
void mod(int b) {
a = b;
}
// C.h: only read
extern int a; // extern const int a doest work
void show() {
printf("%d", a);
}
Can i extern it in other place with const?
I tried in my code, but seems not work.
Can you give me some suggestions? is there any other method to achieve this if extern doest work?

Related

C++ extern variable why can't I define it in main

use.cpp
#include "my.h"
int main()
{
int foo = 7;
print_foo();
print(99);
}
my.h
#pragma once
extern int foo;
void print_foo();
void print(int i);
my.cpp
#include<iostream>
#include "my.h"
void print_foo()
{
std::cout << foo;
}
void print(int i)
{
std::cout << i;
}
So my question is pretty simple I declare an extern int foo in the header file then I DEFINE foo in main, why does this not work? If I don't define foo in main and define it outside of main in use.cpp then it works but when I define it in main() it doesn't. Why?
At global scope, the declaration
extern int foo;
declares a variable named foo that has external linkage, meaning that it might be defined in another translation unit.
At block scope (i.e., as a statement in the body of a function), the definition
int foo = 7;
has no linkage. That means that the compiler will never consider this foo to be the same entity as another foo from another scope. Therefore, this simply creates another variable that's unrelated to the global one, and does not initialize the global one.

static variable followed by extern in the same file

The following piece of code compiles as well as executes fine.
What exactly does the extern int a statement mean after static int a.
Note that If i write static int a after extern int a, the compiler throws error as tests.cpp:6: error: a was declared extern and later static
#include<iostream>
//#include "testh.h"
using namespace std;
static int a;
extern int a;
int main()
{
int a;
a=3;
cout<<a<<endl;
cout<<::a<<endl;
return 0;
}
You can declare a variable static then extern, but not extern then static. The result is that the global a still has internal linkage. There is a very similar example (using b as the variable name) in the language standard doc, section [dcl.stc], that states this.

Using C-defined structures in C++ code

I'm trying to use C-sourced functions in my C++ code. And I have some difficulties, when I try to instantiate in my C++ code structure which is declared in C-header, and then transfer it to C-function by value. Example:
dummyc.h:
#ifndef _DUMMY_C_H_
#define _DUMMY_C_H_
typedef struct {
int a;
int b;
int c;
int d;
}DUMMYS;
int dummyFunction(unsigned int a, unsigned int b, unsigned short c, DUMMYS dummy);
#endif
dummyc.c:
#include "dummyc.h"
int dummyFunction(unsigned int a, unsigned int b, unsigned short c, DUMMYS dummy){
return 1;
}
dummycpp.cpp:
extern "C"{
#include "dummyc.h"
}
int main(){
DUMMYS s = {0,0,0,0};
return dummyFunction(50,50,1,s);
}
During dummyFunction execution I see that data on stack is incorrect. It seems like they where shifted?? How I can do this correctly??? Im using GCC 4.3.4 for ARM.
The 'extern "C"' directive really only matters for the function declarations. This is because C++ has function overloading. I've always embedded the directive around the function signatures in my header files, using '#ifdef __cplusplus'.
#ifndef _DUMMY_C_H_
#define _DUMMY_C_H_
typedef struct {
int a;
int b;
int c;
int d;
}DUMMYS;
#ifdef __cplusplus
extern "C" {
#endif
int dummyFunction(unsigned int a, unsigned int b, unsigned short c, DUMMYS dummy);
#ifdef __cplusplus
}
#endif
#endif
There's no difference in how C and C++ puts members into structs (when the struct is entirely composed of things that are legal in both C and C++).
When you make this change in dummyc.h, you can remove the 'extern "C"' around the #include directive in dummycpp.cpp.

Is there some other way of executing this example in isocpp.org?

I tried to compile and link the second example (see below), in the second FAQ in this link in isocpp.org.
Naturally, this works only for non-member functions. If you want to
call member functions (incl. virtual functions) from C, you need to
provide a simple wrapper. For example:
// C++ code:
class C {
// ...
virtual double f(int);
};
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
Now C::f() can be used like this:
/* C code: */
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
double d = call_C_f(p,i);
/* ... */
}
After several trials, I succeeded executing the example in VS2015. But I'm still not convinced about the declaration extern "C" struct C *p = &c; that I had to use in other.cpp (I simply couldn't make the code to work with anything different than this). Note that the C++ compiler emits the following warning for the alluded declaration:
warning C4099: 'C': type name first seen using 'class' now seen using
'struct'
main.c was compiled with the C compiler and other.cpp with the C++ compiler.
main.c
/* C code: */
#include <stdio.h>
extern struct C *p;
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
double d = call_C_f(p, i);
printf("%f", d);
}
int main()
{
ccc(p, 1);
}
other.cpp
// C++ code:
class C {
public:
virtual double f(int i) { return i; };
} c;
extern "C" struct C *p = &c; // This is the declaration that I'm concerned about
// Is it correct?
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
The line extern "C" struct C *p = &c is IMHO more confusing than really useful. In the same C++ compilation unit you first declare C to be a class, then a struct. As already said in comment with refs in that other question, declaring a class once with struct and once with class may lead to mangling issues in C++ code.
And it is useless, because as C is not a POD struct (it contains method and even a virtual one) it cannot be used from C as a struct, and in fact you only use a pointer to C from c code as an opaque pointer.
So the line should be written:
extern "C" class C *p = &c;
declaring to the compiler that you are defining a pointer to class C with extern linkage named p, pointing to c. Perfectly defined from C++ perspective.
Next from C point of view, you declare the extern pointer p, pointing to an undefined struct C. C will only allow you to use it almost a void pointer, meaning you can affect it and pass it to function, but p->xxx would cause an error because struct C is not fully declared in that compilation unit.
In fact the following code does exactly the same as yours without any warning:
main.c
/* C code: */
#include <stdio.h>
extern struct D *p;
double call_C_f(struct D* p, int i);
void ccc(struct D* p, int i)
{
double d = call_C_f(p, i);
printf("%f", d);
}
int main()
{
ccc(p, 1);
return 0; /* never return random value to environment */
}
other.cpp
// C++ code:
class C {
public:
virtual double f(int i) { return i; };
} c;
extern "C" C *p = &c;
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
The usage of struct D is not a typo. Of course I should have used struct C to avoid confusion for the reader, but it is not a problem for the compiler not for the linker: p in main.c is just a pointer to an opaque not fully declared struct. That's the reason why, it is common to declare such opaque pointers as void *.

How to declare a global variable that could be used in the entire program

I have a variable that I would like to use in all my classes without needing to pass it to the class constructor every time I would like to use it. How would I accomplish this in C++?
Thanks.
global.h
extern int myVar;
global.cpp
#include "global.h"
int myVar = 0; // initialize
class1.cpp
#include "global.h"
...
class2.cpp
#include "global.h"
...
class3.cpp
#include "global.h"
...
MyVar will be known and usable in every module as a global variable. You do not have to have global.cpp. You could initialize myVar in any of the class .cpp's but I think this is cleaner for larger programs.
While I would like to avoid global variables like the plague as our software cannot be multithreaded effectively due to the high reliance on global variables, I do have some suggestions:
Use a Singleton. It will allow you to keep the code and access clean. Part of the problem with a global variable is you don't know what code has modified it. You could set the value of global somewhere in your function relying on the hope that no one else will change it, but function your code calls, fooA, changes it and now your code is a) broken, and b) hard to debug.
If you have to use a global variable without touching the singleton pattern, look at fupsduck's response.
If you're not going to use the Singleton pattern as Lyndsey suggests, then at least use a global function (inside a namespace) to access the variable. This will give you more flexibily in how you manage that global entity.
// mymodule.h
namespace mynamespace // prevents polluting the global namespace
{
extern int getGlobalVariable();
}
// mymodule.cpp
namespace mynamespace
{
int myGlobalVariable = 42;
int getGlobalVariable()
{
return myGlobalVariable;
}
}
Just declare it outside the class:
Header file:
extern int x;
class A {
int z;
public:
A() : z(x++) {}
};
One source file:
int x = 0;
keyword extern
//file1.cpp
int x = 0;
//file1 continues and ends.
//file2.cpp
extern int x; //this gets tied into file1.cpp's x at link time.
//file2.cpp goes on and ends
Declare the variable as extern in a common header.
Define it in any source file.
// L.hpp
struct L { static int a; };
// L.cpp
int L::a(0);
The below solution should be simple enough as per the title "How to declare a global variable that could be used in the entire program
" .
If you want to use it in a different file then make use of extern keyword.
Please let me know if there is any issue with the solution
#include<iostream>
using namespace std;
int global = 5;
class base {
public:
int a;
float b;
base (int x) {
a = global;
cout << "base class value =" << a << endl;
}
};
class derived : public base {
public:
int c;
float d;
derived (float x, int y) : base (y)
{
d = global;
cout << "derived class value =" << d << endl;
}
};
int main ()
{
derived d(0,0);
cout << "main finished" << endl;
return 0;
}
if you want to declare it in different header files/cpp files, just declare it extern outside of other files
//file1.c
int x=1;
int f(){}
//file2.c
extern int x;