我有一篇文章,但我失去了它.它展示并描述了一些人们应该小心的C/C++技巧.其中一个让我感兴趣,但现在我正在尝试复制它,我无法将其编译.
这个概念是可以随意改变constC/C++ 中a的值
它是这样的:
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
Run Code Online (Sandbox Code Playgroud)
我想向朋友展示这个,但现在我错过了一步.有谁知道它开始编译和工作缺少什么?
ATM我从'const int*'到'int*'的转换无效,但是当我读到我试过的文章时,它运行得很好.
sfo*_*sen 42
你需要抛弃常量:
linux ~ $ cat constTest.c
#include <stdio.h>
void modA( int *x )
{
*x = 7;
}
int main( void )
{
const int a = 3; // I promisse i won't change a
int *ptr;
ptr = (int*)( &a );
printf( "A=%d\n", a );
*ptr = 5; // I'm a liar, a is now 5
printf( "A=%d\n", a );
*((int*)(&a)) = 6;
printf( "A=%d\n", a );
modA( (int*)( &a ));
printf( "A=%d\n", a );
return 0;
}
linux ~ $ gcc constTest.c -o constTest
linux ~ $ ./constTest
A=3
A=5
A=6
A=7
linux ~ $ g++ constTest.c -o constTest
linux ~ $ ./constTest
A=3
A=3
A=3
A=3
Run Code Online (Sandbox Code Playgroud)
另外,常见的答案在g ++ 4.1.2中不起作用
linux ~ $ cat constTest2.cpp
#include <iostream>
using namespace std;
int main( void )
{
const int a = 3; // I promisse i won't change a
int *ptr;
ptr = const_cast<int*>( &a );
cout << "A=" << a << endl;
*ptr = 5; // I'm a liar, a is now 5
cout << "A=" << a << endl;
return 0;
}
linux ~ $ g++ constTest2.cpp -o constTest2
linux ~ $ ./constTest2
A=3
A=3
linux ~ $
Run Code Online (Sandbox Code Playgroud)
顺便说一句......这是永远不推荐的...我发现g ++不允许这种情况发生..所以这可能是你遇到的问题.
Ada*_*eld 12
只是一个猜测,但一个常见的问题是为什么一个人不能转换int**为a const int**,这看起来是合理的(毕竟,你只是添加一个const,这通常是好的).原因是如果你可以这样做,你可能会意外地修改一个const对象:
const int x = 3;
int *px;
const int **ppx = &px; // ERROR: conversion from 'int**' to 'const int**'
*ppx = &x; // ok, assigning 'const int*' to 'const int*'
*px = 4; // oops, just modified a const object
Run Code Online (Sandbox Code Playgroud)
这是一个非常不直观的结果,但是确保const在这种情况下无法修改对象的唯一方法(注意没有类型转换)是使第3行成为错误.
您只能const在第一级间接添加时不添加强制转换:
int * const *ppx = &px; // this is ok
*ppx = &x; // but now this is an error because *ppx is 'const'
Run Code Online (Sandbox Code Playgroud)
在C++中,如果const不使用某种类型的类型转换,则无法修改对象.您必须使用C风格的强制转换或C++风格const_cast来删除const-ness.任何其他尝试这样做都会导致编译器错误.
And*_*ian 10
请注意,标准未定义任何抛弃constness的尝试.从标准的7.1.5.1开始:
除了可以修改任何声明为mutable的类成员之外,任何在其生命周期内修改const对象的尝试都会导致未定义的行为.
在使用此示例之后:
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
Run Code Online (Sandbox Code Playgroud)
因此,简而言之,使用标准C++是不可能的.
此外,当编译器遇到类似的声明时
const int a = 3; // I promisse i won't change a
Run Code Online (Sandbox Code Playgroud)
可以自由地将任何出现的'a'替换为3(实际上做同样的事情#define a 3)
回到时间的迷雾,我们古代程序员使用FORTRAN.FORTRAN通过引用传递了所有参数,并没有进行任何类型检查.这意味着很容易意外地改变甚至是文字常量的值.您可以将"3"传递给SUBROUTINE,然后它会更改,因此每次从那时起您的代码都有一个"3",它实际上会像一个不同的值.让我告诉你,这些都是难以找到并修复的错误.