-1

It is known and useful features that:

  • const type qualifier prohibits writing (modification) of a variable
  • register storage-class specifier prohibits taking address of a variable

However, is there a standard way to prohibit reading (via assignment) of a variable?

For example, for such variable only writing and/or taking address is permitted.

Reason of the question: need to conditionally prohibit reading (via assignment) of some variable. Does the language provide any way to do it? If no, then why?

UPD. Readers may be interested as well: C: check at compile time or at run time that variable has static storage-class specifier.

pmor
  • 5,392
  • 4
  • 17
  • 36
  • Of what possible use could that be? – Lee Daniel Crocker Jun 03 '21 at 19:34
  • 2
    Data which can never be read from seems quite useless. [XY Problem](https://en.wikipedia.org/wiki/XY_problem)? – tkausl Jun 03 '21 at 19:36
  • 3
    @tkausl It's useful in embedded programming, since that's the way some hardware works. – user3386109 Jun 03 '21 at 19:37
  • @tkausl Also *kind of* useful for encryption keys, that can be used by cryptographic hardware, but not readable via regular memory access. But for that I would expect the *hardware* to restrict the access, and not C. – Eugene Sh. Jun 03 '21 at 19:41
  • 1
    Note that `const` is a hint to the compiler that it can put the variable in read-only memory, e.g. in flash memory instead of RAM. For write-only memory, there's the `volatile` keyword, which forces the compiler to actually write the requested value to the requested address. But nothing in the C language stops code from trying to write to read-only memory, or read from write-only memory. – user3386109 Jun 03 '21 at 19:51
  • 5
    I weary of these questions. Overall, they seem to draw from the Stack Overflow community without giving much in return. – Eric Postpischil Jun 03 '21 at 19:53
  • @LeeDanielCrocker Imagine how fast you can make WOM (Write-Only-Memory)! Infinite bandwidth! – Andrew Henle Jun 03 '21 at 19:55
  • `const` does not prohibit writing to an object. It requires the implementation to diagnose if you attempt to write through a `const`-qualified type (but an implementation could allow it and still be conforming to the C standard) and makes the behavior of writing to an object defined with `const` not defined by the standard. – Eric Postpischil Jun 03 '21 at 20:00
  • @user3386109 In that case the *hardware* would make the call - either to return some special value (zero, 0xFF whatsoever) or raise some hardware signal that will translate into some memory violation error. Sure, it would be nice to intersept it in compile time, but the point here is not to protect a variable, but a specific memory address(es), which are only assigned in the run time. – Eugene Sh. Jun 03 '21 at 20:02
  • @user3386109 ***`For write-only memory, there's the volatile keyword, which forces the compiler to actually write`*** nonsense. https://godbolt.org/z/xr57drxvr. It is not how `volatile` works at all. `volatile` says only that the variable is side effects prone. `volatile const` says the compiler that the programmer cannot change it, but something else can, so it has to read every time when it is used. Practical example: read only hardware registers. They can be changed by the hardware, but have to be written by the program – 0___________ Jun 03 '21 at 20:59

3 Answers3

2

No, not as far as I know.

I don't know why, one reason might be that it's something that is only fantastically rarely useful. You (in my opinion) don't actually explain why you want this, which further emphasizes that's a rather convoluted/weird thing to want.

unwind
  • 391,730
  • 64
  • 469
  • 606
2

It is known and useful features that:

  • const type qualifier prohibits writing (modification) of a variable

Yes.

  • register storage-class specifier prohibits taking address of a variable

True, but that's not the primary purpose of the register storage class.

However, is there a standard way to prohibit reading (via assignment) of a variable?

I take it that you want to forbid ...

_Write_only int x = 1;
int y = x;

... but no, there is no way to do that. If you have an lvalue expression designating an existing object, such as is required to set the value of that object, then that expression can be used to read the current value of the object, too.

Reason of the question: need to conditionally prohibit reading (via assignment) of some variable.

That's not much of a reason. You seem to just be saying, "I need it because I need it."

Does the language provide any way to do it? If no, then why?

If by "why" you are asking for us to support our answers, then I refer you to paragraph 6.3.2.1/2 of the standard, where you will find this:

Except when it is the operand of the sizeof operator, the _Alignof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)

That does not leave any room for the kind of semantics you asked about.

If you mean something else by the "why" question then we can only speculate, but I don't personally find the situation in any way surprising. In particular, I don't find the existence of const and register as suggesting that there should be a qualifier with the effect you describe.


If you want an object that can only be written, not read, by a piece of code X then you can declare it outside the scope of X and with linkage that does not afford access from X, and provide a function that X can call to modify the object's value. For example, the object might be declared static at file scope in a different translation unit, with an external writer function declared in that unit:

static int protected;

void set_protected(int value) {
    protected = value;
}

Code in other translation units could then use the function to set the variable's value, but could not access the object directly to read its value.

Note well that that all goes out the window if you allow X to get the address of the protected object, as that can be dereferenced to gain access.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

You need to hide your variables from the program code

#define CREATE_PROTECTED(var, type, val) type set_##var(type v){static type var = val; return var;}
#define GET(var) set_##var(val)

CREATE_PROTECTED(myvar, size_t, 500);

size_t foo(void)
{
    return GET(myvar)
}
0___________
  • 60,014
  • 4
  • 34
  • 74