const/volatile修饰标识符的进一步论证

zenny_chen 2007-05-12 01:55:25
const int *p = NULL; 相当于 int const *p = NULL;
下面要写一对与上面一对表达式更清晰的陈述:

const int (*p) = NULL; 相当于 int const (*p) = NULL;

这样其实比起第一对看起来更加清晰。const修饰(*p),即限定p指针所指地址内容的值。

再看下面:

int * const p = NULL;

更清晰地表述为:int (* const p) = NULL;

这样,很明显可以看到const修饰标识符p,即限定p指针的值。

要注意的是没有int (const * p) = NULL;这样的语法。
因为这样一来,对int的修饰会产生冲突。由于const *p对于C/C++而言本身就是一个合法的正则表达式语句。const *p = NULL; 完全OK,这时p作为int const*类型。

利用括号对指针类型进行限定是比较有用的分析技巧。

比如说以下情况:

typedef int ARRAY[10];

void main(void)
{
ARRAY *p; // p是什么类型?
}

那么对于类型定义情况,我们公司很多程序员都搞不清楚。尤其像以上这种情况。
加个括号看看:ARRAY (*p);

分析:由于ARRAY是int[10]类型,将它代入就成为:int[10] (*p);
调整一下:int (*p)[10]; 所以比较自然地得出了p的类型为:int(*)[10]。

指针标记*与标识符靠拢时总是与标识符进行一同规归约。

typedef const int CINT;

CINT *p = NULL; // p是什么类型?

同样地,加括号:CINT (*p) = NULL; 就和const int (*p)一样了。

typedef int* PINT;

PINT const p = NULL; // p是什么类型?

同样地,加括号,不过这里实际上没什么必要了,因为p作为一个单独的标识符没有指针对它进行修饰。const PINT (p) = NULL; 由于PINT为(int*)类型,因此这里的const就是对标识符p作修饰,由于p已经为(int*),因此p的类型为int* const。

若为:PINT const (*p) = NULL;那么p类型为:int* const *。第一个int*是由PINT得到的。

若是:PINT (* const p) = NULL; 那么p类型为int* * const
...全文
459 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangwang1103 2007-07-09
  • 打赏
  • 举报
回复
mark
Demon_Agua 2007-07-07
  • 打赏
  • 举报
回复
to zenny_chen(ACE Intercessor):
左联修饰理论?
我觉得你应该从“*”的右结合性来考虑
zxmam 2007-07-06
  • 打赏
  • 举报
回复
这个与int const* p 和 const int *p是一样的。
我认为这说法是错误的。
const int *p 表示p指向的值是常量不能被改变的,如:*p=55肯定报错.
int const *p 表示常量p,它不能再指向其它int,此变量的值还是可以改变的如:*p=55或其它值。
所以说它们是完全不一样的一个是修饰指针一个是修饰指针指向的值。
mymtom 2007-05-13
  • 打赏
  • 举报
回复
回楼主:
对不起了,我搞错了!
我漏了一个分号!
您说得没错!
zenny_chen 2007-05-13
  • 打赏
  • 举报
回复
To feitianmayi1986():

我不是说得很清楚了吗?const int (*p)与int const (*p)都是int const*类型。

这个与int const* p 和 const int *p是一样的。也就是说int和const进行交换位置没有问题。
飞天蚂蚁1986 2007-05-12
  • 打赏
  • 举报
回复
const int (*p) = NULL; 相当于 int const (*p) = NULL;
楼主啊,你说的都是真的吗?
不是呀,前面的是说p所指的是一个整型常量,后面的是一个说这个指针是常量的吧!
liang851128 2007-05-12
  • 打赏
  • 举报
回复
学习 学习 再学习.
指向常量的指针
常指针
指向常量的常指针
等等这些 以前看了很多
不过lz讨论类型的方法还是比较有意思的.
zenny_chen 2007-05-12
  • 打赏
  • 举报
回复
回复mymtom():

#include <stdio.h>

int const (*p) = NULL;

const int (*q) = NULL;

int main(void)
{
int a = 10;

p = q = &a;

printf("The answer is: %d\n", *q);

return 0;
}
我在MinGW下,用GCC3.4.2编译连接、运行都通过。

你是不是没打好啊?
zenny_chen 2007-05-12
  • 打赏
  • 举报
回复
我自己到是有一套理论来理解这种复杂的声明——左联修饰。不过由于这种解释对于一些情况也不太好用,比如说:int (* const p) = NULL; 基于这种情况,只能分步进行解析:首先p为int*类型,然后const修饰p。

那么如果不采用括号,确实可以用这套理论:

const、volatile以及restrict这些限定词遵循左联修饰原则。

如:int const *p = NULL; const限定int类型
int* const p; const限定int*类型

这样也可以非常清楚地搞懂const修饰什么。
更复杂一点的:

int* const **p = NULL; // const限定int*
int** const *p = NULL; // const限定int**

void (* const p)(void) = NULL; // const限定void(*)(void)

void (* const *p)(void) = NULL; // const限定void(*)(void)

int (** const p)[10] = NULL; // const限定int(**)[10]

显然,左联修饰理论可以非常清晰地确定左值应该以何种类型与被const所限定的右值进行匹配。

但是这只能作为一种判断依据。不应该完全以这种规则来实现const限定的正则表达式。因为会有如下情况:

const int *p = NULL; // const放在int前面(左边)的情况

int (* const p) = NULL; // 带有括号的情况
mymtom 2007-05-12
  • 打赏
  • 举报
回复
谢谢LS
antterminator 2007-05-12
  • 打赏
  • 举报
回复
其实要解释复杂的C和C++的声明,只需要遵循right-left-rule就可以了:
http://www.codeproject.com/cpp/complex_declarations.asp
zenny_chen 2007-05-12
  • 打赏
  • 举报
回复
我看一下GCC源代码实现。
mymtom 2007-05-12
  • 打赏
  • 举报
回复
对标准的理解还是不够啊!
也许是GCC的BUG?
zenny_chen 2007-05-12
  • 打赏
  • 举报
回复
不会吧,我在VS.NET2005以及ViusalDSP++中都通过编译运行了。

我再试试GNU 3.4.2
mymtom 2007-05-12
  • 打赏
  • 举报
回复
const int (*p) = NULL; 相当于 int const (*p) = NULL;
楼主啊,你说的都是真的吗?
可是我这里:
/usr/home/jerry/src/cpp/faq$ cat const.c
#include <stdio.h>

const int (*p1) = NULL
int const (*p2) = NULL;

int main(void)
{
int i;

p1 = &i;
p2 = &i;

return (0);
}
/usr/home/jerry/src/cpp/faq$ make const
cc -O -pipe -g -Wall const.c -o const
const.c:4: error: syntax error before "int"
const.c: In function `main':
const.c:11: error: `p2' undeclared (first use in this function)
const.c:11: error: (Each undeclared identifier is reported only once
const.c:11: error: for each function it appears in.)
*** Error code 1

Stop in /usr/home/jerry/src/cpp/faq.
/usr/home/jerry/src/cpp/faq$ cc --version
cc (GCC) 3.4.2 [FreeBSD] 20040728
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
expter 2007-05-12
  • 打赏
  • 举报
回复
學習啊

我一般就記住指針常量
常量指針就行了
多了昏啊

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧