Mon*_*all 32 c pointers type-safety
我有这个非常简单的测试函数,我正在使用它来弄清楚const限定符发生了什么.
int test(const int* dummy)
{
*dummy = 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个问题让我对GCC 4.8.3产生了错误.然而这个编译:
int test(const int* dummy)
{
*(char*)dummy = 1;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因此,似乎const限定符只有在我使用参数而不转换为其他类型时才有效.
最近我见过使用的代码
test(const void* vpointer, ...)
Run Code Online (Sandbox Code Playgroud)
至少对我来说,当我使用void*时,我倾向于将它转换为char*以用于堆栈中的指针算法或跟踪.const void*如何阻止子程序函数修改vpointer指向的数据?
bol*_*lov 46
const int *var;
Run Code Online (Sandbox Code Playgroud)
const是合同.通过接收const int *参数,您"告诉"调用者您(被调用函数)不会修改指针指向的对象.
您的第二个示例通过抛弃const限定符然后修改接收指针指向的对象来显式中断该合约.从来没有这样做过.
这个"合同"由编译器强制执行.*dummy = 1不会编译.通过告诉编译器你真的知道自己在做什么并让你这样做,演员是一种绕过它的方法.不幸的是,"我真的知道我在做什么"通常不是这样.
const 也可以由编译器用来执行否则无法进行的优化.
未定义的行为说明:
请注意,虽然转换本身在技术上是合法的,但修改声明为constUndefined Behavior 的值.所以从技术上讲,原始函数是可以的,只要传递给它的指针指向声明为可变的数据.否则它是未定义的行为.
在帖子的最后更多关于这一点
至于动机和使用让我们采取的参数strcpy和memcpy功能:
char* strcpy( char* dest, const char* src );
void* memcpy( void* dest, const void* src, std::size_t count );
Run Code Online (Sandbox Code Playgroud)
strcpy对char字符串进行memcpy操作,对通用数据进行操作.虽然我用的strcpy作为例子,下面的讨论正是上是相同的,但char *并const char *为strcpy和void *和const void *为memcpy:
dest是char *因为在缓冲区dest中函数会放置副本.该函数将修改此缓冲区的内容,因此它不是const.
src是const char *因为该函数只读取缓冲区的内容src.它不会修改它.
只有通过查看函数的声明,调用者才能断言以上所有内容.通过契约strcpy不会修改作为参数传递的第二个缓冲区的内容.
const并且void是正交的.这是所有关于以上的讨论const适用于任何类型(int,char,void,...)
void * 在C中用于"通用"数据.
更多关于未定义的行为:
情况1:
int a = 24;
const int *cp_a = &a; // mutabale to const is perfectly legal. This is in effect
// a constant view (reference) into a mutable object
*(int *)cp_a = 10; // Legal, because the object referenced (a)
// is declared as mutable
Run Code Online (Sandbox Code Playgroud)
案例2:
const int cb = 42;
const int *cp_cb = &cb;
*(int *)cp_cb = 10; // Undefined Behavior.
// the write into a const object (cb here) is illegal.
Run Code Online (Sandbox Code Playgroud)
我从这些例子开始,因为它们更容易理解.从这里只有一步功能参数:
void foo(const int *cp) {
*(int *)cp = 10; // Legal in case 1. Undefined Behavior in case 2
}
Run Code Online (Sandbox Code Playgroud)
情况1:
int a = 0;
foo(&a); // the write inside foo is legal
Run Code Online (Sandbox Code Playgroud)
案例2:
int const b = 0;
foo(&b); // the write inside foo causes Undefined Behavior
Run Code Online (Sandbox Code Playgroud)
我必须再次强调:除非你真的知道你在做什么,所有在现在和未来工作的人都是专家并理解这一点,你有一个好的动力,除非满足以上所有要求,从不抛弃了常量!
Run Code Online (Sandbox Code Playgroud)int test(const int* dummy) { *(char*)dummy = 1; return 0; }
不,这不起作用.抛弃constness(使用真正的const数据)是未定义的行为,例如,如果实现将const数据放入ROM中,您的程序可能会崩溃."它有效"这一事实并没有改变您的代码格式错误的事实.
至少对我来说,当我使用void*时,我倾向于将它转换为char*以用于堆栈中的指针算法或跟踪.const void*如何阻止子程序函数修改vpointer指向的数据?
A const void*表示指向某些无法更改的数据的指针.为了阅读它,是的,你必须将它转换为具体的类型,如char.但是我说读书,而不是写作,这也是UB.
这涉及更深入这里.C允许您完全绕过类型安全:防止这种情况是您的工作.
| 归档时间: |
|
| 查看次数: |
21571 次 |
| 最近记录: |