假设我有一些像这样的代码:
void foo (void *ptr) {
const struct some *azaza = (const struct some *)ptr;
azaza->some_field = 123; // inadvertently assignment => error
// ...
演员表中确实需要const
指示符吗?
编辑:foo
是具有特定原型的回调函数,我无法更改(这不在我的代码中) )。
答案 0 :(得分:6)
在您的特定情况下,您甚至不需要强制转换。对于void *
,只有在取消引用时才需要广播。这样就足够了:
const struct some *azaza = ptr;
但出于兴趣,
#gcc test.c
:
// 1)
const struct some *azaza = ptr;
azaza->some_field = 123; // error: assignment in read-only object
// 2)
struct some *azaza = (const struct some *)ptr; // (!)warning: initialization discards ‘const’ qualifier
azaza->some_field = 123;
#gcc test.c -pedantic-errors
:
// 1)
const struct some *azaza = ptr;
azaza->some_field = 123; // error: assignment in read-only object
// 2)
struct some *azaza = (const struct some *)ptr; // error: initialization
// discards ‘const’ qualifier
azaza->some_field = 123;
总结:
const
。const
(出于某种奇怪的原因._。)而没有 -pedantic-errors
,则使用-意外分配不会导致错误后果。答案 1 :(得分:0)
如果将toArray()
所指向的值声明为const,则您要执行的操作是未定义的行为。您不应该更改const值。您只能使用cast删除const并仅在最初未使用const声明的情况下修改值。
ptr
否则,如果未使用const声明,为什么不这样做:
int modify(void *ptr) {
some_t *value = ptr;
value->member = 0; // here where UB could happen
}
int main(void)
{
some_t obj0 = {0};
const some_t obj1 = {0};
modify(&obj0); // OK
modify(&obj1); // leads to undefined behaviour
return 0;
}
答案 2 :(得分:0)
这取决于您要执行的操作。您的代码段由于以下原因而令人困惑:
该函数采用非常量指针,这意味着该函数可能希望更改'ptr'指向的内容。
然后,在输入函数时,将'ptr'强制转换为const指针。因此,现在编译器认为该函数无意修改ptr指向的内容。因此,在程序调用时发生错误是正常的。
azaza->some_field = 123; // not allowed !
根据您的意图,可以用以下两种形式之一编写函数:
选项1:该函数无意修改ptr指向的内容:
void foo( const void * ptr ) {
const struct some * azaza = (const struct some *) ptr ;
// ... do something other than writing to 'azaza', for example:
printf("Some field: %d\n", azaza->some_field ) ;
}
选项2:该函数确实打算修改ptr指向的内容:
void foo(void * ptr ) {
struct some * azaza = (struct some *) ptr ;
// ... write to 'azaza', for example:
azaza->some_field = 123 ;
}
答案 3 :(得分:0)
如果我理解您的问题,则您希望实例受const保护,并且您在问写是否足够:
const struct some *azaza = (struct some *)ptr;
而不是
const struct some *azaza = (const struct some *)ptr;
我要说的是,因为const属性可以由编译器自动应用,但不能被删除。如果这是C ++,那将是最少的足够代码,但是正如其他人提到的那样,用C编写代码就足够了:
const struct some *azaza = ptr;
由于C允许将void指针强制转换为其他任何指针类型,因此可以推断出constness。但是,我认为C ++指令可以使代码更清晰可读。
请注意,如果您已经有一个const指针,则不能在不“放弃”该const的情况下将其分配给非const指针。为了符合C ++规范,我倾向于放入2个强制类型转换,尽管C会自己接受任一类型:
void foo (const void *ptr) {
struct some *azaza = (struct some *)(void*)ptr;
azaza->some_field = 123; // intentional overwrite!
// ...