Exposing globals as read-only

A

Ark Khasin

Consider a problem of exposing some
T foo;
for read-only access by other modules, in order to prevent inadvertent
(as opposed to malicious) writes to it. I cannot afford and/or do not
want to incur the overhead of access functions. A solution could be:

foo.h:
extern T foo;
#define foo ((const T)foo) //hide the original foo

foo.c:
#include "foo.h"
#undef foo
T foo;

There can be variations on this theme avoiding the often deprecated
#undef, like
foo.h:
extern T foo;
#ifndef OWNER_foo
#define foo ((const T)foo) //hide the original foo
#endif

foo.c:
#define OWNER_foo
#include "foo.h"
T foo;

What are NG's opinions on whether
- it looks right aesthetically
- it is a good idea to "overload" the identifier
- this can be a recommended practice (pattern) for a company's coding
standard
- (probably OT) this can confuse popular or bundled code browsers,
debuggers etc
 
F

Falcon Kirtaran

Ark said:
Consider a problem of exposing some
T foo;
for read-only access by other modules, in order to prevent inadvertent
(as opposed to malicious) writes to it. I cannot afford and/or do not
want to incur the overhead of access functions. A solution could be:

foo.h:
extern T foo;
#define foo ((const T)foo) //hide the original foo

foo.c:
#include "foo.h"
#undef foo
T foo;

There can be variations on this theme avoiding the often deprecated
#undef, like
foo.h:
extern T foo;
#ifndef OWNER_foo
#define foo ((const T)foo) //hide the original foo
#endif

foo.c:
#define OWNER_foo
#include "foo.h"
T foo;

What are NG's opinions on whether
- it looks right aesthetically
- it is a good idea to "overload" the identifier
- this can be a recommended practice (pattern) for a company's coding
standard
- (probably OT) this can confuse popular or bundled code browsers,
debuggers etc

I wonder if it would work to do something like:

extern const T foo;
 
A

Ark Khasin

Falcon said:
I wonder if it would work to do something like:

extern const T foo;
No: foo.c would have a conflict between the definition and the
declaration. Fooling the compiler by not including foo.h not only is
bad, but also causes UB (most likely, a linker's complaint)
 
I

Ian Collins

Ark said:
Consider a problem of exposing some
T foo;
for read-only access by other modules, in order to prevent inadvertent
(as opposed to malicious) writes to it. I cannot afford and/or do not
want to incur the overhead of access functions. A solution could be:
Provide an inline function in a header.
 
S

Shri

Can this be done???

Put all the functions who want Write access to this global variable in
a different file, and make the variable "global static". so now the
variable is visible only to the functions that are defined in the new
file.

Now to give other modules read access, put a function in the new file
which when called will just return the value of the global variable (I
think this is not a big overhead).

Example:

New.c

static int Variable; // this is a global static variable and hence it
is visible only to the functions defined in this same file.

Func1()
{

.....
;;;;

}

//All functions which need write access

int GetVarValue()
{
return Variable;
}


Foo.c

int GetVarValue();

Func00()
{

....
;;;

}

//All functions that do not need write access to the global variable.
 
A

Ark Khasin

Shri said:
Now to give other modules read access, put a function in the new file
which when called will just return the value of the global variable (I
think this is not a big overhead).
The whole point of the exercise is to avoid access functions.
-- Ark
 
A

Ark Khasin

Ian said:
You don't expose the variable, just the function that returns its value.
I may be thick but I don't know how an inline function would know what
the variable is unless it's declared... Could you please offer a snippet
of code?
-- Ark
 
I

Ian Collins

Ark said:
I may be thick but I don't know how an inline function would know what
the variable is unless it's declared... Could you please offer a snippet
of code?

You're not, I am....
 
F

Falcon Kirtaran

Ark said:
I may be thick but I don't know how an inline function would know what
the variable is unless it's declared... Could you please offer a snippet
of code?
-- Ark

Generally, that looks something like:

inline T getfoo() { return foo; };

This function goes into the file where foo is declared, after the
declaration, so it does know about it.
 
R

Richard Tobin

Ark Khasin said:
I may be thick but I don't know how an inline function would know what
the variable is unless it's declared...

Obviously it can't, but if you're only trying to protect against
inadvertent modification you could give the variable an obscure name
and the inline function a short, natural, documented one.

-- Richard
 
B

Ben Bacarisse

Ark Khasin said:
Consider a problem of exposing some
T foo;
for read-only access by other modules, in order to prevent inadvertent
(as opposed to malicious) writes to it. I cannot afford and/or do not
want to incur the overhead of access functions. A solution could be:

foo.h:
What are NG's opinions on whether
- it looks right aesthetically
- it is a good idea to "overload" the identifier
- this can be a recommended practice (pattern) for a company's coding
standard
- (probably OT) this can confuse popular or bundled code browsers,
debuggers etc

Forgive me for no answering these questions but I'd suggest you
consider:

foo.h:
extern const T *foop;

and in foo.c:

static T foo = {/* stuff */};
const T *foop = &foo;

It costs you a dereference, and may not fit your problem (since I
suspect you may have a reason not to change the way foo is currently
accessed) but it has the benefit of simplicity. Anyway, posted just
in case you can change the accesses.
 
J

Jack Klein

Consider a problem of exposing some
T foo;
for read-only access by other modules, in order to prevent inadvertent
(as opposed to malicious) writes to it. I cannot afford and/or do not
want to incur the overhead of access functions. A solution could be:

foo.h:
extern T foo;
#define foo ((const T)foo) //hide the original foo

foo.c:
#include "foo.h"
#undef foo
T foo;

There can be variations on this theme avoiding the often deprecated
#undef, like
foo.h:
extern T foo;
#ifndef OWNER_foo
#define foo ((const T)foo) //hide the original foo
#endif

foo.c:
#define OWNER_foo
#include "foo.h"
T foo;

What are NG's opinions on whether
- it looks right aesthetically
- it is a good idea to "overload" the identifier
- this can be a recommended practice (pattern) for a company's coding
standard
- (probably OT) this can confuse popular or bundled code browsers,
debuggers etc

The best esthetic solution I ever came up for was a case like this:

static T foo;
const T* read_foo = &foo;

....and of course, in a header file:

extern const T* read_foo;

This allows clients read-only access to foo by dereferencing the
pointer. It does not protect against malicious modification, since
there is no undefined behavior in casting away const qualification if
the actual object was defined non constant. But it does object to
accidental modification, which you say is your objective.

I occasionally use this in places where the overhead of a function
call would be burdensome, as inside ISRs.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top