为什么C中的字符串用' const'?

时间:2016-10-10 23:31:57

标签: c string pointers const

例如,为什么不:

char *s= "example";

而不是:

const char *s= "example";

我知道const使它不可更改,但为什么在编译第一个时会收到错误?

此外,该概念如何适用于

int * x;

vs

const int *x;

我看到第二个使用了更多,使用" cons int *"是好的做法?

3 个答案:

答案 0 :(得分:12)

没有要求使用const,但这是一个好主意。

在C中,字符串文字是类型char[N]的表达式,其中N是字符串的长度加1(对于终止'\0'空字符)。但是,尝试修改与字符串文字对应的数组具有未定义的行为。许多编译器安排将该阵列存储在只读存储器中(不是物理ROM,而是由操作系统标记为只读的存储器)。 (在大多数上下文中,数组表达式转换为指向数组对象的初始元素的指针表达式。)

创建字符串文字const会更有意义,但旧版本的C中不存在const关键字,它会破坏现有代码。 (C ++确实创建了字符串文字const)。

此:

char *s= "example"; /* not recommended */

在C中实际上是完全有效的,但它有潜在的危险性。如果在此声明之后,您执行以下操作:

s[0] = 'E';

然后您尝试修改字符串文字,并且行为未定义。

此:

const char *s= "example"; /* recommended */

也有效;通过评估字符串文字得到的char*值安全,安静地转换为const char*。并且它通常比第一个版本更好,因为它允许编译器在您尝试修改字符串文字时警告您(在编译时捕获错误比在运行时更好)。

如果您的第一个示例出现错误,那么您可能无意中将代码编译为C ++而不是C - 或者您正在使用gcc' s -Wwrite-strings选项或类似的东西。 (-Wwrite-strings生成字符串文字const;它可以提高安全性,但也可能导致gcc拒绝或至少警告有效的C代码。)

答案 1 :(得分:2)

在Visual Studio 2015处于警告级别4时,无论是编译为C还是C ++,都会编译并运行:

#include <stdio.h>

char *s1= "example\n";
const char *s2= "example\n";

int main(int argc, char **argv)
{
    printf(s1);  // prints "example"
    s1[2] = 'x';
    printf(s1);  // prints "exxmple"

    printf(s2);

    return 0;
}

如果我添加这一行,它将无法使用我所知道的每个编译器编译为C或C ++:

    s2[2] = 'x'; // produces compile error

这是const关键字旨在避免的错误。它只是告诉编译器不允许对指向的对象进行赋值。

指针指向charint或其他任何内容都无关紧要。 const关键字对所有指针都有相同的效果,这样就不可能(很好,很难)分配给声明为const的事物。

答案 2 :(得分:0)

用作值的字符串文字将编译为不应修改的rdd = sc.parallelize([(1, 8), (1, 3), (1, -1), (2, 4), (2, 5), (2, 2), (3, 2), (3, 4)]) rdd = rdd.map(lambda tup: (tup[0], tuple([tup[1], abs(tup[0] - tup[1])]))) rdd.reduceByKey(lambda v1, v2: v1 if v1[1] < v2[1] else v2).mapValues(lambda x: x[0]).collectAsMap() 数组。尝试修改它会调用未定义的行为。出于向后兼容性的历史原因,其类型为char,但实际上应该是char []。您可以启用额外的编译器警告来更改此值,并指示编译器将此类字符串视为const char []