7

有人告诉我,如果我在 ANSI C 中编码以按使用变量的顺序声明,则断言指针不为空且索引在界限内,并在使用变量之前进行初始化。

如果我声明一个const,我可以在一段断言和代码之后初始化它吗?

在 Java 中,最终初始化必须在声明时进行,但是通过 ANSI C 实现是否一致,我可以初始化const一次,但不一定在声明时进行?

4

7 回答 7

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;
}
于 2009-09-13T10:53:58.433 回答
3

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

此代码产生error: assignment of read-only variable 'foo'(GCC 4):

const int foo;
foo = 4;

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

int * const foo;
foo = 4;
于 2009-09-13T10:28:43.880 回答
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
于 2009-09-13T10:46:59.363 回答
2

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

void func()
{
    int y;

    // Do assertions
    assert(something);
    {
        int const x = 5;
        // Function body
     }
}
于 2009-09-13T10:42:18.393 回答
2

缺少其他显示的块作用域和 C99 声明方法,答案是否定的;您不能推迟 const 变量的初始化。无论如何, const 对于局部变量不是很有用。我在 C 中使用 const 关键字的主要时间是:

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

如果我认为它可以帮助读者理解函数,我有时会声明局部变量 const,但这种情况很少见。

于 2010-07-08T07:29:58.590 回答
1

如果您正在谈论拆分定义

const int x = 2;

分为两部分:

const int x;

x = 2;

恐怕这在 C 中是不可能的。

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

针对各种评论:

const int * p;

不是const 变量声明。它是一个指向 const int 的非常量指针变量的声明。

你可以声明

extern const int x;

但是在执行代码、断言检查等之后仍然不能初始化 x。

于 2009-09-13T10:32:15.940 回答
0

如果您想在LHS上抛弃 const ,请使用以下命令:

const int n = 0;

*((int*)&n) = 23;
于 2011-06-09T21:36:37.130 回答