C:`const`关键字的行为

时间:2009-09-13 10:21:12

标签: c const keyword language-implementation

我被告知如果我在ANSI-C中编码以按照将要使用的变量的顺序声明,断言指针不是null并且索引在边界内,并且在使用之前初始化变量。

如果我声明一个const,我可以在一段断言和代码之后初始化它吗? 在Java中,最终初始化必须在声明时进行,但是通过ANSI-C实现它是否一致,我可以初始化const一次但不一定在声明时?

7 个答案:

答案 0 :(得分:9)

Java编译器具有少量流逻辑,允许您在声明后发送final个变量。这是合法的Java:

final int something;

if ( today == Friday )
    something = 7;
else
    something = 42;

Java将检测是否有任何分支未定义最终值。它不会分析条件,所以这不是合法的Java,即使它在逻辑上相似:

final int something;

if ( today == Friday )
    something = 7;

if ( today != Friday )
    something = 42;

在ANSI C89中,必须在声明它们的语句中初始化const个变量(extern除外)。

const int something = ( today == Friday ) ? 7 : 42;

声明上的extern修饰符告诉编译器该变量是在不同的编译单元(或此编译单元中的其他位置)初始化的。

在ANSI C99中,您可以混合声明和代码,因此您可以在断言和代码块之后声明并初始化const变量。 1999 ANSI C的可移植性仍然存在问题。

解决C89的问题是要注意代码之前的声明规则在块范围而不是函数范围内工作,所以你可以这样做:

#include<stdio.h>

int main ( void )
{
    printf ( "wibble\n" );

    {
        const int x = 10;

        printf ( "x = %d\n", x );
    }

    return 0;
}

答案 1 :(得分:3)

const个变量是只读的,必须在定义它们的地方进行初始化。

此代码生成error: assignment of read-only variable 'foo'(gcc4):

const int foo;
foo = 4;

const指针同样如此(注意:const int *不是const指针,而是指向const的指针):

int * const foo;
foo = 4;

答案 2 :(得分:3)

请注意,即使在C89中,您也可以通过引入一个仅用于额外范围的裸块来将定义更接近第一次使用的位置。之前:

int a, b, c;

a = 12;
// do some stuff with a

b = 17;
// do some stuff with a and b

c = 23;
// do some stuff with a, b, and c

后:

int a = 12;
// do some stuff with a
{
    int b = 17
    // do some stuff with a and b
    {
        int c = 23;
        // do some stuff with a, b and c
    }
}

当然,使用C99,您可以定义除块开头之外的变量:

int a = 12;
// do some stuff with a

int b = 17
// do some stuff with a and b

int c = 23;
// do some stuff with a, b and c

答案 3 :(得分:2)

您无法在函数体内声明后初始化const,但您可以在断言后打开一个块:

void func()
{
    int y;
    //do assertions
    assert(something);
    {
        int const x = 5;
        // function body
     }
}

答案 4 :(得分:2)

除了块范围和其他已经显示的C99声明方法之外,答案是否定的;你不能推迟const变量的初始化。无论如何,const对局部变量不是很有用。我在C中使用const关键字的主要时间是:

  • 函数参数(或基于参数的局部变量指针)中的指针,其中函数遵守不修改指向数据的约定。 const关键字有助于确保函数实现遵守不修改的要求(它需要特殊的工作量来摆脱const)并允许此要求通过多个函数调用传播。
  • 用于声明我希望存储在二进制文件的只读部分中的编译时常量表(查找表,预定义永久对象等),以便它们在运行时不使用额外的物理资源。

我有时会声明局部变量const,如果我认为它会帮助读者理解一个函数,但这种情况非常罕见。

答案 5 :(得分:1)

如果你在谈论拆分定义

const int x = 2;

分为两部分:

const int x;

x=2;

我担心在C中不可能。

如果我是你,我会尽力确保理解你描述的编码规则的意图。我怀疑理智的编码规则会阻止初始化变量(甚至是非常量变量)。

回应各种意见:

const int * p;

不是const变量的声明。它是对const int的非const指针变量的声明。

您可以声明

extern const int x;

但是在执行代码,断言检查后,你仍然无法初始化x ......

答案 6 :(得分:0)

如果你想在LHS上抛弃const,那怎么样?

const int n = 0;

*((int*)&n) = 23;