简体   繁体   English

C 中的常量结构成员是如何处理的?

[英]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?如果是这样,处理常量结构成员的公认做法是什么?

It's undefined behavior.这是未定义的行为。

The C11 draft n1570 says: C11 草案 n1570 说:

6.7.3 Type qualifiers 6.7.3 类型限定符

... ...

... ...

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.如果尝试通过使用具有非 const 限定类型的左值来修改使用 const 限定类型定义的 object,则行为未定义。

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:我对此的解释是:为了符合标准,您只能在 object 创建(又名初始化)期间设置 const 成员的值,例如:

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.它可能在大多数系统上都能正常工作,但根据 C11 标准,它仍然是未定义的行为。

Also see memcpy with destination pointer to const data另请参阅带有指向 const 数据的目标指针的 memcpy

How are constant struct members handled in C? C 中的常量结构成员是如何处理的?

Read the C11 standard n1570 and its §6.7.3 related to the const qualifier.阅读 C11 标准n1570及其与const限定符相关的 §6.7.3。

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.这取决于您是否更关心严格遵守 C 标准,还是关心实际实现。 See this draft report (work in progress in June 2020) discussing these concerns.请参阅讨论这些问题的这份报告草案(2020 年 6 月正在进行的工作)。 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 .您可能不会在Covid 呼吸器的嵌入式软件(或某些ICBM内部)和 web 服务器(如lighttpd或诸如libonion 之类的库或某些FastCGI应用程序)上花费相同的精力在廉价的消费电器中或在一些廉价租用的 Linux VPS上运行。

Consider also using static analysis tools such as Frama-C or the Clang static analyzer on your code.还可以考虑在代码上使用 static 分析工具,例如Frama-CClang static 分析器

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). 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).

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.对于像“所有 X 必须是 Y”或“没有 X 可能是 Z”这样的陈述是有意义的,X 的定义必须具有不仅满足所有 X 的条件,而且明确排除所有不满足的对象要求为 Y 或允许为 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.鉴于这种情况,许多操作,包括更新具有恒定成员的结构,很可能属于 realm 的操作,标准不要求实现有意义地处理,但标准的作者会期望实现会有意义地处理无论如何。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM