Pra*_*tic 2 c casting const c99 language-lawyer
何时抛弃const
非法?
在许多情况下,const
它只是用户利益的注释,由编译器强制执行.这个问题要求什么时候抛弃const
是严格违法的,C99标准的哪一部分禁止它(如果有的话)?
我怀疑在某些情况下它一定是非法的,因为我发现const
全局范围内的函数指针有时被gcc内联.如果这些函数指针可以在程序的后期合法修改,那么这种优化将是无效的.另外我很确定我已经阅读了关于何时丢弃const
在StackOverflow上是非法的解释,但我找不到它.(我认为答案是const
只有当一个变量最初没有被声明为时才能抛弃const
.)
我已经标记了这个C99,因为我希望这是C99标准中指定的内容,但如果答案可以解释C99的gcc,clang和MSVC实现的共同行为,那么这对我来说也足够了.
(显然这是一个非常基本的问题,所以我确实试过并没有找到专门针对C标准的副本.如果其他人可以指出我一个完全重复,我会很乐意结束投票.在任何一种情况下,我认为这个问题标题至少可以帮助SSO解决这类问题.)
AnT*_*AnT 11
抛弃永恒从不违法.你可以随意和合法地做到你想要的.但是,在将const括起来之后尝试修改指向的对象可能会导致未定义的行为(或者可能不会,这取决于具体情况).
C99明确指出
6.7.3类型限定符
5如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为未定义.
(C11为6.7.3/6).
请注意,const
在C(和C++)中使用两个独立且非常不同的角色:对象本身的 const限定和对象访问路径的 const限定.
const int a = 42; // `a` is a const-qualifiet object
int b = 5; // `b` is not const-qualified
const int *p = &b; // `*p` is a const-qualified access path to `b`
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,constness可以合法地抛弃,并且结果非const访问路径可以用于修改对象,前提是对象本身不是const
*(int *) p = 6; // nothing formally wrong with it
Run Code Online (Sandbox Code Playgroud)
这就是我们有能力抛弃语言中的常数的原因.
但是前者(对象本身的常量)不能被覆盖
*(int *) &a = 43; // undefined behavior
Run Code Online (Sandbox Code Playgroud)
原因很简单 - 一个const对象可以物理地位于只读内存中.即使不是这样,编译器仍然可以在假设对象的值永远不会改变的情况下编译代码.
这意味着在声明中
const int *const cp = &b;
Run Code Online (Sandbox Code Playgroud)
这两者const
有着截然不同的含义.第一个(最左边)是"软" const
,如果条件合适,可以覆盖它.但第二个const
是"硬" const
,不能被覆盖.
因此,当您说" const
仅仅是编译器强制执行的用户利益的注释"时,只有访问路径的const限定才适用.当谈到对象本身的const-qualifications时,通常只是一个纯粹的概念编译器强制的"注释".