强制转换说明符的必要性

时间:2019-05-31 16:27:11

标签: c linux gcc casting const

假设我有一些像这样的代码:

void foo (void *ptr) {
    const struct some *azaza = (const struct some *)ptr;
    azaza->some_field = 123; // inadvertently assignment => error
    // ...

演员表中确实需要const指示符吗?


编辑:foo是具有特定原型回调函数,我无法更改(这不在我的代码中) )。

4 个答案:

答案 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;

总结:

  1. 您无需投放const
  2. 如果您仅在强制转换中使用const(出于某种奇怪的原因._。)而没有 -pedantic-errors ,则使用-意外分配不会导致错误后果。

答案 1 :(得分:0)

  1. 如果将toArray()所指向的值声明为const,则您要执行的操作是未定义的行为。您不应该更改const值。您只能使用cast删除const并仅在最初未使用const声明的情况下修改值。

    ptr
  2. 否则,如果未使用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!
  // ...