为什么编译器允许你“写”这里有一个常量变量吗?

发布于 2024-10-02 19:21:56 字数 271 浏览 3 评论 0原文

为什么你可以这样欺骗编译器:

const int a = 5;
*((int*)&a)=5;   // VC/armcc does not complain

当上面的内容是“删节”时,相当于:

const int *ptr2const = &a;
int *ptr = ptr2const;      // as expected error is raised here
*ptr = 5;

Why can you kind of cheat compiler this way:

const int a = 5;
*((int*)&a)=5;   // VC/armcc does not complain

when above is "abridged" equivalent of this:

const int *ptr2const = &a;
int *ptr = ptr2const;      // as expected error is raised here
*ptr = 5;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

峩卟喜欢 2024-10-09 19:21:56

强制转换是告诉编译器“我知道我在做什么”的方式,所以它不会抱怨。不幸的是,在这种情况下,您将调用未定义的行为。

Casting is your way of telling the compiler "I know what I'm doing", so it doesn't complain. Unfortunately, in this instance, you will invoke undefined behaviour.

緦唸λ蓇 2024-10-09 19:21:56

C 风格的强制转换允许您像示例中那样放弃常量。在 C++ 中,您通常会使用新的样式强制转换,例如 static_cast<>,它不允许您放弃常量。只有 const_cast<> 允许您执行此操作。

C-style casts allow you to cast away constness like in your example. In C++, you would normally use the new style casts such as static_cast<>, which don't allow you to cast away constness. Only const_cast<> allows you to do that.

风筝有风,海豚有海 2024-10-09 19:21:56

为了等效,第二个片段的第二行

int *ptr = ptr2const;      // as expected error is raised here

应写为

int *ptr = (int *)ptr2const;

To be equivalent, the 2nd line of the 2nd snippet

int *ptr = ptr2const;      // as expected error is raised here

should be written as

int *ptr = (int *)ptr2const;
看春风乍起 2024-10-09 19:21:56

因为 C 抛弃了很多类型安全,以获得更快的速度。它不能阻止你做不正确的事情。它可能会尝试警告您正在做不正确的事情,但如果这是您的目标,您总是可以绕过编译器。

Because C throws away a lot of type safety in order to gain a lot of speed instead. It cannot prevent you from doing incorrect things. It may try to warn you that you are doing incorrect things, but you can always work around the compiler if that is your goal.

唯憾梦倾城 2024-10-09 19:21:56

将常量转换为字符串,您可能会发现,虽然编译器会让您放弃const(尽管这可能是不可取的),但链接器可能会将常量字符串放入在只读内存中导致运行时崩溃。

Convert your constant to a string and you may find that while the compiler will let you cast away the const (inadvisable though it may be), the linker may put the constant string in read-only memory leading to a runtime crash.

许仙没带伞 2024-10-09 19:21:56

C 风格的强制转换,例如 (int*) 等价于 C++ const_cast ,它们能够抛弃常量性,因此您可以通过使用它们来回避常量正确性,尽管不推荐这种使用(可能导致未定义的行为)。

int main()
{
    const int x = 1;
    (int&)x = 2;
    std::cout << x << std::endl;
}

在我的系统上,上面的代码将 1 写入标准输出。您可能会遇到不同的行为。

另一方面......

void foo(const int& x)
{
    (int&)x = 2;
}

int main()
{
    int x = 1;
    foo(x);
    std::cout << x << std::endl;
}

这为我写了2。不同之处在于,foo 中使用的 const 是 const 作为类型限定符,而在第一个示例的 main 中,它被用作类型限定符。存储类。查看变量是否使用 const 声明为存储类并不总是那么容易,因此最好不要依赖 const_cast 或 C 风格强制转换来放弃 const。

在大多数情况下最好只使用static_cast,因为这会在编译时以编译错误的形式警告您任何可疑行为。

C-style casts, such as (int*) are equivalent to C++ const_cast in their ability to cast away constness, so you can side-step const-correctness by using them, although such use is unrecommended (can lead to undefined behaviour).

int main()
{
    const int x = 1;
    (int&)x = 2;
    std::cout << x << std::endl;
}

On my system, the above writes 1 to stdout. You might experience different behaviour.

On the other hand...

void foo(const int& x)
{
    (int&)x = 2;
}

int main()
{
    int x = 1;
    foo(x);
    std::cout << x << std::endl;
}

This writes 2 for me. The difference is that the const used in foo is const as a type qualifier, while in the main in the first example it was used as a storage class. It's not always easy to see whether a variable was declared with const as a storage class, so it's best not to rely on a const_cast or C-style cast to cast away const.

It's best just to use static_cast in most situations as this will warn you at compile time of any suspect behaviour in the form of a compile error.

⊕婉儿 2024-10-09 19:21:56

这只“有效”,因为变量是本地变量,并且实现通常无法在本地(自动)变量上强制执行常量性(至少在获取变量地址的情况下不会)。但就语言规范而言,这属于未定义行为的领域。

如果您在全局/静态变量上尝试此操作,您很快就会发现大多数实现可以并且确实通过将变量放入来强制const只读内存,可以在程序的多个实例之间共享。

This only "works" because the variable is local, and implementations have no way to enforce const-ness on a local (automatic) variable in general (at least not if the address of the variable is ever taken). But as far as the language specification is concerned, this is in the realm of undefined behavior.

If you try this on a global/static variable, you'll quickly find that most implementations can and do enforce const by putting the variable in read-only memory which can be shared between multiple instances of your program.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文