在C++和C中作为函数参数的'const int'和'int const'的区别

140

考虑:

int testfunc1 (const int a)
{
  return a;
}

int testfunc2 (int const a)
{
  return a;
}

这两个函数在所有方面都相同吗?还是有区别?

我对C语言的答案感兴趣,但如果C++语言中有什么有趣的东西,我也想知道。


现在的C语言中是否有const关键字?以前没有,但我对C 99标准不是很熟悉。 - Onorio Catenacci
8
不需要那么高,C90就够了。但在原始的 K&R C 中并没有包含它。 - Mark Baker
3
"这是C89和ANSI中的一个关键词。我不知道它在Kerningham和Richie时代是否也是一个关键词。" - Nils Pipenbrinck
8
这个网站可以将“C语言鬼话”翻译成英文。http://www.cdecl.org/ - Motti
6
我会说“把C语言胡言乱语翻译成英文胡言乱语”,不过还是很好的 :) - Kos
这是一个等价的问题,与const int *,const int * const和int const *之间有什么区别?检查一下! :) - alandawkins
9个回答

372

技巧在于从后往前阅读声明(从右到左):

const int a = 1; // read as "a is an integer which is constant"
int const a = 1; // read as "a is a constant integer"

两者是同一件事情。因此:

a = 2; // Can't do because a is constant

阅读反向技巧特别适用于处理更复杂的声明,例如:

const char *s;      // read as "s is a pointer to a char that is constant"
char c;
char *const t = &c; // read as "t is a constant pointer to a char"

*s = 'A'; // Can't do because the char is constant
s++;      // Can do because the pointer isn't constant
*t = 'A'; // Can do because the char isn't constant
t++;      // Can't do because the pointer is constant

6
"char const *u"是什么意思?它是“指向常量字符”的指针,还是一个常量指向字符的指针?似乎有歧义。标准规定是前者,但要了解这一点,必须考虑运算符优先级和结合性。 - Panayiotis Karabassis
7
所有的词应被视为形容词链,不要改变它们的位置。 char const * 从左往右读是:"pointer, const, char"。它是一个指向常量字符的指针。当你说 "一个指针是常量" 时,"常量" 形容词在指针上。所以,在这种情况下,你的形容词顺序应该是:"const, pointer, char"。但你是正确的,这个技巧存在歧义。这确实是一个 "技巧",而不是一个明确的 "规则"。 - Ates Goral
5
当你声明一个混合了数组、函数、指针和函数指针的类型时,倒序阅读就不再适用了(遗憾的是)。然而,你可以按螺旋式来阅读这些乱七八糟的声明。有些人被这些声明搞得很沮丧,所以他们发明了Go语言。 - Martin J.H.
@Martin J.H:它们不能通过typedef分解吗?或者使用引用来消除间接性? - Peter Mortensen

204

const TT const 是相同的。但对于指针类型来说就更加复杂了:

  1. const char* 是指向常量 char 的指针
  2. char const* 是指向常量 char 的指针
  3. char* const 是指向 (可变) char 的常量指针

换句话说,(1) 和 (2) 是相同的。使指针(而不是指向的内容)成为 const 的唯一方法是使用后缀-const

这就是为什么许多人更喜欢始终将 const 放在类型的右侧(“东 const”风格):它使其相对于类型的位置保持一致且易于记忆(据说这也更容易教给初学者)。


2
C 语言确实有 const,假设:static const char foo[] = "foo"; 你最好不要改变 foo。 - James Antill
4
K&R C没有const关键字;C90(和C99)有。相比C++,它的用法有所限制,但仍然很有用。 - Mark Baker
2
这对于引用也是适用的吗? - Ken
3
@Ken 是的,没错。 - Konrad Rudolph
1
@Maverick 是的,与指针相同的解析规则。 - Konrad Rudolph
显示剩余4条评论

16

它们之间没有区别。它们都声明“a”为一个无法更改的整数。

差异开始出现的地方是在使用指针时。

这两个代码片段:

const int *a
int const *a

声明 "a" 为一个指向不可变整数的指针。可以给 "a" 赋值,但不能更改 "*a" 的值。

int * const a

声明"a"为指向整数的常量指针。"*a"可以被赋值,但"a"不能。

const int * const a

声明"a"为指向常量整数的常量指针。不能对"a"或"*a"进行赋值。

static int one = 1;

int testfunc3 (const int *a)
{
  *a = 1; /* Error */
  a = &one;
  return *a;
}

int testfunc4 (int * const a)
{
  *a = 1;
  a = &one; /* Error */
  return *a;
}

int testfunc5 (const int * const a)
{
  *a = 1;   /* Error */
  a = &one; /* Error */
  return *a;
}

10

Prakash的说法是正确的,尽管关于指针情况可能需要更详细的解释。

"const int* p"是指向int类型的指针,不允许通过该指针更改int类型的值。"int* const p"是指向int类型的指针,不能被修改为指向其他int类型。

请参见https://isocpp.org/wiki/faq/const-correctness#const-ptr-vs-ptr-const


5

const intint const相同,这也适用于C中的所有标量类型。通常情况下,在C语言中声明标量函数参数为const是不必要的,因为C采用按值传递的语义,意味着对变量所做的任何更改都是局部的,仅限于其封闭函数。


5

这两者是相同的,但在C++中,总是在右侧使用const有一个很好的理由。因为const成员函数必须这样声明,所以你会保持一致:

int getInt() const;

它将函数中的this指针从Foo * const更改为Foo const * const详见此处。

3
这是一种完全不同的常量。 - Justin Meiners
1
是的,问题是关于“const int”和“int const”的区别,您的回答与此无关。 - Justin Meiners

3

对于 int 类型,它们是相同的。

而对于 int* 类型,它们是不同的。


5
(const int *) 和 (int const *) 是相同的,它们只是与 (int *const) 不同。 - James Antill

3

这不是一个直接的答案,而是一个相关的提示。为了保持清晰,我总是使用“把const放在外面”的惯例,其中“外面”指的是最左边或最右边。这样就没有混淆——const适用于最近的东西(类型或*)。例如:



int * const foo = ...; // Pointer cannot change, pointed to value can change
const int * bar = ...; // Pointer can change, pointed to value cannot change
int * baz = ...; // Pointer can change, pointed to value can change
const int * const qux = ...; // Pointer cannot change, pointed to value cannot change

6
也许更好的做法是使用规则“const 使其左侧的所有内容都变为 const”。例如,“int * const foo”使指针“const”,因为指针在其左侧。然而,你会发现第二行“int const * bar”将使 int 变为 const,因为它在其左侧。“int const * const * qux”会使 int 和指针都变成 const,因为两者都在其左侧。 - Mecki

2
我认为在这种情况下它们是相同的,但这里有一个例子,其中顺序很重要:
const int* cantChangeTheData;
int* const cantChangeTheAddress;

2
确实如此,但 int const * 与第一个相同,因此 int 和 const 的顺序无关紧要,只有 * 和 const 的顺序才重要。 - Mark Baker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接