我有一篇文章,但我把它弄丢了。 它展示并描述了一些人们应该小心的 C/C++ 技巧。 其中之一让我感兴趣,但现在我正在尝试复制它,但我无法将其编译。
这个概念是,在 C/C++ 中,可能会意外更改 const 的值。
事情是这样的:
const int a = 3; // I promise I won't change a
const int *ptr_to_a = &a; // I still promise I won't change a
int *ptr;
ptr = ptr_to_a;
(*ptr) = 5; // I'm a liar; a is now 5
我想向朋友展示这个,但现在我错过了一个步骤。 有谁知道它开始编译和工作缺少什么?
ATM 我收到从“const int*”到“int*”的无效转换,但是当我阅读这篇文章时,我尝试了它,效果很好。
I had an article, but I lost it. It showed and described a couple of C/C++ tricks that people should be careful. One of them interested me but now that I am trying to replicate it I'm not being able to put it to compile.
The concept was that it is possible to change by accident the value of a const
in C/C++
It was something like this:
const int a = 3; // I promise I won't change a
const int *ptr_to_a = &a; // I still promise I won't change a
int *ptr;
ptr = ptr_to_a;
(*ptr) = 5; // I'm a liar; a is now 5
I wanted to show this to a friend but now I'm missing a step. Does anyone know what's missing for it to start compiling and working?
ATM I'm getting invalid conversion from 'const int*' to 'int*' but when I read the article I tried and it worked great.
发布评论
评论(19)
你需要抛弃常量:
顺便说一句,常见的答案在 g++ 4.1.2 中不起作用
..从来不建议这样做...我发现 g++ 不允许这种情况发生..所以这可能是问题所在你正在经历。
you need to cast away the constness:
also the common answer doesn't work in g++ 4.1.2
btw.. this is never recommended... I found that g++ doesn't allow this to happen.. so that may be the issue you are experiencing.
请注意,标准未定义任何放弃常量的尝试。 从标准7.1.5.1开始:
就在使用这个例子之后:
所以简而言之,使用标准 C++ 不可能实现您想要做的事情。
此外,当编译器遇到这样的声明时,
它可以随意将任何出现的“a”替换为 3(实际上与
#define a 3
执行相同的操作)Note any attempt to cast away constness is undefined by the standard. From 7.1.5.1 of the standard:
And right after this example is used:
So in short what you want to do isn't possible using standard C++.
Further when the compiler encounters a declaration like
it is free to replace any occurance of 'a' with 3 (effectively doing the same thing as
#define a 3
)回到过去,我们古程序员使用 FORTRAN。 FORTRAN 通过引用传递其所有参数,并且不进行任何类型检查。 这意味着即使是文字常量的值也很容易意外更改。 您可以将“3”传递给子例程,它返回时会发生变化,因此从那时起,每次您的代码有“3”时,它实际上都会表现得像一个不同的值。 让我告诉你,这些错误很难发现和修复。
Back in the mists of time, we paleo-programmers used FORTRAN. FORTRAN passed all its parameters by reference, and didn't do any typechecking. This meant it was quite easy to accidentally change the value of even a literal constant. You could pass "3" to a SUBROUTINE, and it would come back changed, and so every time from then on where your code had a "3", it would actually act like a different value. Let me tell you, those were hard bugs to find and fix.
只是猜测,但一个常见的问题是为什么不能将
int**
转换为const int**
,这乍一看似乎是合理的(毕竟,您只需添加一个const
,这通常是可以的)。 原因是,如果您可以这样做,您可能会意外修改const
对象:这是一个非常不直观的结果,但这是确保您无法修改
的唯一方法本例中的 const
对象(请注意没有类型转换)会使第 3 行出错。只允许在第一级间接添加不进行强制转换的
const
:在 C++ 中,不使用某种类型强制转换就不可能修改
const
对象。 您必须使用 C 风格的强制转换或 C++ 风格的const_cast
来删除const
性质。 任何其他尝试这样做都会导致某个地方出现编译器错误。Just a guess, but a common question is why one can't convert an
int**
to aconst int**
, which at first appears to be reasonable (after all, you're just adding aconst
, which is normally ok). The reason is that if you could do this, you could accidentally modify aconst
object:It's a very non-intuitive result, but the only way to make sure that you can't modify a
const
object in this case (note how there are no typecasts) is to make line 3 an error.You're only allowed to add
const
without a cast at the FIRST level of indirection:In C++, it is impossible to modify a
const
object without using a typecast of some sort. You'll have to use either a C-style cast or a C++-styleconst_cast
to remove theconst
-ness. Any other attempt to do so will result in a compiler error somewhere.你尝试过这个吗?
这应该有助于它的编译,但由于演员阵容的原因,这并不是偶然的。
Did you try this?
That should help it compile but it's not really by accident due to the cast.
在 C++ 中,使用 Microsoft Visual Studio-2008
在 C 中,const 变量可以通过其指针进行修改; 然而这是未定义的行为。 const 变量永远不能用作数组声明中的长度。
在C++中,如果const变量是用纯常量表达式初始化的,那么即使尝试修改后,也不能通过其指针修改其值,否则可以通过其指针修改const变量。
如果纯整型常量变量的值大于 0,则可以将其用作数组声明中的长度。
纯常量表达式由以下操作数组成。
数字常量(常量),例如 2, 10.53
#define 指令定义的符号常量
枚举常量
纯const变量,即本身用纯常量表达式初始化的const变量。
不允许使用非常量变量或易失性变量。
In C++, Using Microsoft Visual Studio-2008
In C, a const variable can be modified through its pointer; however it is undefined behavior. A const variable can be never used as length in an array declaration.
In C++, if a const variable is initialized with a pure constant expression, then its value cannot be modified through its pointer even after try to modify, otherwise a const variable can be modified through its pointer.
A pure integral const variable can be used as length in an array declaration, if its value is greater than 0.
A pure constant expression consists of the following operands.
A numeric literal (constant ) e.g. 2, 10.53
A symbolic constant defined by #define directive
An Enumeration constant
A pure const variable i.e. a const variable which is itself initialized with a pure constant expression.
Non-const variables or volatile variables are not allowed.
其中一些答案指出,编译器可以优化变量“a”,因为它被声明为 const。 如果您确实希望能够更改
a
的值,那么您需要将其标记为易失性
当然,将某些内容声明为
const 易失性
应该真正说明这是多么愚蠢。Some of these answers point out that the compiler can optimize away the variable 'a' since it is declared
const
. If you really want to be able to change the value ofa
then you need to mark it asvolatile
Of course, declaring something as
const volatile
should really illustrate just how silly this is.这将产生运行时错误。 因为int是静态的。 未处理的异常。 访问冲突写入位置 0x00035834。
this will create a runtime fault. Because the int is static. Unhandled exception. Access violation writing location 0x00035834.
您可能想使用 const_cast:
不过,我不是 100% 确定这会起作用,我对 C/C++ 有点生疏:-)
const_cast 的一些阅读:http://msdn.microsoft.com/en-us/library/bz6at95h(VS.80).aspx
You probably want to use const_cast:
I'm not 100% certain this will work though, I'm a bit rusty at C/C++ :-)
Some readup for const_cast: http://msdn.microsoft.com/en-us/library/bz6at95h(VS.80).aspx
你正在看的文章可能一直在讨论
和
之间的区别,或者我记得——我这里除了 Java 工具之外什么都没有,所以无法测试:)
The article you were looking at might have been talking about the difference between
and
Or so I recall-- I don't have anything but Java tools here, so can't test :)
我正在寻找如何在 const 之间进行转换,我发现了这个 http://www.possibility.com /Cpp/const.html 也许它对某人有用。 :)
I was looking on how to convert between consts and I found this one http://www.possibility.com/Cpp/const.html maybe it can be useful to someone. :)
我测试了下面的代码,它成功地更改了常量成员变量。
控制台输出是:
在这里,障碍是,您必须定义与常量成员变量一样多的指针。
I have tested the code below and it successfully changes the constant member variables.
The console output is:
Here, the handicap is, you have to define as many pointers as number of constant member variables you have.
在大多数情况下,编译器将常量作为宏使用,只需在要使用它的地方替换它的值即可。 一个简单的 C 示例,说明如何更改常量并使用它:
In most cases, the compiler works with a constant as a macro by simply substituting its value where you want to use it. A simple C example of how to change a constant and work with it:
我们可以通过以下代码更改 const 变量值:
we can change the const variable value by the following code :
最终解决方案:它将更改
const
变量的值;Final Solution: it will change
const
variable a value;您缺少的步骤是您不需要 int* 指针。 该行:
实际上表示您不会更改 ptr_to_a,而不是 a。 因此,如果您将代码更改为如下所示:
a 现在为 5。您可以通过 ptr_to_a 更改 a,而不会发出任何警告。
编辑:
以上是不正确的。 事实证明,我将类似的技巧与shared_ptr混淆了,在shared_ptr中,您可以访问原始指针并修改内部数据值,而不会发出任何警告。 即:
将产生5个。
The step you're missing is that you don't need the int* pointer. The line:
actually says you won't change ptr_to_a, not a. So if you changed your code to read like this:
a is now 5. You can change a through ptr_to_a without any warning.
EDIT:
The above is incorrect. It turns out I was confusing a similar trick with a shared_ptr, in which you can get access to the raw pointer and modify the internal data value without firing off any warnings. That is:
Will produce 5.