user13709754
user13709754

Reputation:

How are constant struct members handled in C?

Is it OK do do something like this?

struct MyStruct {
    int x;
    const char y; // notice the const
    unsigned short z;
};
struct MyStruct AStruct;
fread(&MyStruct, sizeof (MyStruct), 1,
      SomeFileThatWasDefinedEarlierButIsntIncludedInThisCodeSnippet);

I am changing the constant struct member by writing to the entire struct from a file. How is that supposed to be handled? Is this undefined behavior, to write to a non-constant struct, if one or more of the struct members is constant? If so, what is the accepted practice to handle constant struct members?

Upvotes: 2

Views: 545

Answers (3)

supercat
supercat

Reputation: 81169

The Standard is a bit sloppy in its definition and use of the term "object". For a statement like "All X must be Y" or "No X may be Z" to be meaningful, the definition of X must have criteria that are not only satisfied by all X, but that would unambiguously exclude all objects that aren't required to be Y or are allowed to be Z.

The definition of "object", however, is simply "region of data storage in the execution environment, the contents of which can represent values". Such a definition, however, fails to make clear whether every possible range of consecutive addresses is always an "object", or when various possible ranges of addresses are subject to the constraints that apply to "objects" and when they are not.

In order for the Standard to unambiguously classify a corner case as defined or undefined, the Committee would have to reach a consensus as to whether it should be defined or undefined. If the Committee members fundamentally disagree about whether some cases should be defined or undefined, the only way to pass a rule by consensus will be if the rule is written ambiguously in a way that allows people with contradictory views about what should be defined to each think the rule supports their viewpoint. While I don't think the Committee members explicitly wanted to make their rules ambiguous, I don't think the Committee could have been consensus for rules that weren't.

Given that situation, many actions, including updating structures that have constant members, most likely falls in the realm of actions which the Standard doesn't require implementations to process meaningfully, but which the authors of the Standard would have expected that implementations would process meaningfully anyhow.

Upvotes: 0

How are constant struct members handled in C?

Read the C11 standard n1570 and its §6.7.3 related to the const qualifier.

If so, what is the accepted practice to handle constant struct members?

It depends if you care more about strict conformance to the C standard, or about practical implementations. See this draft report (work in progress in June 2020) discussing these concerns. Such considerations depend on the development efforts allocated on your project, and on portability of your software (to other platforms).

It is likely that you won't spend the same efforts on the embedded software of a Covid respirator (or inside some ICBM) and on the web server (like lighttpd or a library such as libonion or some FastCGI application) inside a cheap consumer appliance or running on some cheap rented Linux VPS.

Consider also using static analysis tools such as Frama-C or the Clang static analyzer on your code.

Regarding undefined behavior, be sure to read this blog.

See also this answer to a related question.

I am changing the constant struct member by writing to the entire struct from a file.

Then endianness issues and file system issues are important. Consider perhaps using libraries related to JSON, to YAML, perhaps mixed to sqlite or PostGreSQL or TokyoCabinet (and the source code of all these open source libraries, or from the Linux kernel, could be inspirational).

Upvotes: 2

4386427
4386427

Reputation: 44274

It's undefined behavior.

The C11 draft n1570 says:

6.7.3 Type qualifiers

...

...

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

My interpretation of this is: To be compliant with the standard, you are only allowed to set the value of the const member during object creation (aka initialization) like:

struct MyStruct AStruct = {1, 'a', 2};  // Fine

Doing

AStruct.y = 'b';   // Error

should give a compiler error.

You can trick the compiler with code like:

memcpy(&AStruct, &AnotherStruct, sizeof AStruct);

It will probably work fine on most systems but it's still undefined behavior according to the C11 standard.

Also see memcpy with destination pointer to const data

Upvotes: 3

Related Questions