2011-12-14 53 views
16

请考虑下面的代码:的typedef指针常量的怪事

typedef struct Person* PersonRef; 
struct Person { 
    int age; 
}; 

const PersonRef person = NULL; 

void changePerson(PersonRef newPerson) { 
    person = newPerson; 
} 

出于某种原因,编译comlaining约只读不可转让的价值。但const关键字不应该使指针为const。有任何想法吗?

+2

“但const关键字不应该使指针为常量。”咦?简短的回答:不要使用typedefs,他们只是在那里混淆你。记住他们,直到你需要他们。 – wildplasser 2011-12-14 12:29:44

+12

@wildplasser:“不要使用typedefs”不是很好的建议。也许“不要隐藏在typedef后面的指针”更合适...... – 2011-12-14 12:32:08

+1

我不同意。它*是一个很好的建议。隐藏typedef后面的结构与隐藏指针一样令人困惑。它只会污染你的精神命名空间。即使没有语法突出显示,我更容易和更快地读“struct person * p”,然后“pPerson p”。 – wildplasser 2011-12-14 12:36:53

回答

33

注意

typedef int* intptr; 
const intptr x; 

是不一样的:

const int* x; 

intptr是指向int的指针。 const intptr是指向int的常量指针,而不是指向常量int的指针。

因此,在一个typedef指针后,我不能使它对内容的const?

有一些丑陋的方式,比如gcc的typeof macro

typedef int* intptr; 
intptr dummy; 
const typeof(*dummy) *x; 

,但是,你看,这是毫无意义的,如果你知道背后intptr类型。

5
const PersonRef person = NULL; 

struct Person*const person= NULL; 

所以你consting指针,而不是对象。

0

你在声明

person = newPerson; 

获取和错误

error: assignment of read-only variable ‘person’ 

,因为你已经声明者为const因此其价值只能只读.... 常量的值不能改变

如果你要改变那个vatiable那么你为什么要把它作为const?

删除const关键字您的代码将工作正常

1

永不隐藏指针的typedef的背后,则是真的不好的做法,只会创建错误。

一个这样臭名昭着的bug是被声明为const的typedef:ed指针类型将被视为“指向非常数数据的常量指针”,而不是“指向常数数据的非常数指针”,它是人们直觉上期望的是什么。这是你的程序中发生的事情。


解决方案:

typedef struct 
{ 
    int age; 
} Person; 

const Person* person = NULL; // non-constant pointer to constant Person 
3

虽然问题已经被解决了答案上面,我很想念......的原因

因此,也许作为一个经验法则:

  1. const总是指它的前身令牌。
  2. 如果没有这样的情况,它就是“强制”它的后继标记。

这个规则可以真正帮助你声明一个指向const指针的指针或者其他东西。

无论如何,考虑到这一点,就应该得到清楚为什么

struct Person *const person = NULL; 

声明了一个常量指针的可变结构。

想想看,你的typedef “groups”struct Person与指针标记*。 所以,写

const PersonRef person = NULL; 

你的编译器看到的是这样的(伪代码):

const [struct Person *]person = NULL; 

由于没有什么const的离开,它deklares令牌它是正确的struct Person *不变。

嗯,我想,这就是为什么我不喜欢通过typedefs隐藏指针,而我喜欢typedefs这样的。那写什么

typedef struct Person { ... } Person; 
const Person *person; /*< const person */ 
Person *const pointer; /*< const pointer to mutable person */ 

它应该是很清楚的编译器和人类,你在做什么。