C:“const”关键字的行为

发布于 2024-08-04 04:23:35 字数 208 浏览 2 评论 0原文

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

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

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

I've been told that if I'm coding in ANSI C to declare in the order that the variables will be used, assert that pointers are not null and that indices are within bounds, and to initialize just before usage of the variable.

If I declare a const can I initialize it after a block of assertions and code?

In Java final initializations must occur at declaration, yet is it consistent through ANSI C implementations that I can initialize a const once, but not necessarily at the time of declaration?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

伴梦长久 2024-08-11 04:23:35

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;
}

The Java compiler has a small amount of flow logic to allow you to initalise final variables after their declaration. This is legal Java:

final int something;

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

Java will detect if any branches leave the final value undefined. It won't analyse the conditions, so this is not legal Java, even though it's logically similar:

final int something;

if ( today == Friday )
    something = 7;

if ( today != Friday )
    something = 42;

In ANSI C89, const variables ( other than extern ) must be initialised in the statement they are declared in.

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

The extern modifier on a declaration tells the compiler that the variable is initialised in a different complation unit ( or elsewhere in this compilation unit ).

In ANSI C99, you can mix declarations and code, so you can declare and initialise a const variable after a block of assertions and code. Portability of 1999 ANSI C remains an issue.

A work around for C89 is to note that the rules for declarations preceding code work at block scope rather than function scope, so you can do this:

#include<stdio.h>

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

    {
        const int x = 10;

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

    return 0;
}
蘸点软妹酱 2024-08-11 04:23:35

请注意,即使在 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

Be aware that even in C89, you can often move the definition closer to the point of first use by introducing a bare block just for the extra scope. Before:

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

After:

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
    }
}

With C99 of course, you can define variables other than at the beginning of a block:

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
欲拥i 2024-08-11 04:23:35

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

此代码产生错误:只读变量'foo'的分配(GCC 4):

const int foo;
foo = 4;

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

int * const foo;
foo = 4;

const variables are read-only and must be initialised where they're defined.

This code produces error: assignment of read-only variable 'foo' (GCC 4):

const int foo;
foo = 4;

The same goes for const pointers (note here: const int * is not a const pointer, but a pointer to const):

int * const foo;
foo = 4;
陌伤浅笑 2024-08-11 04:23:35

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

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

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

Short of the block scope and C99 declaration methods other have shown, the answer is no; you cannot defer initialization of a const variable. Anyway, const is not very useful for local variables. The main times I use the const keyword in C are:

  • Pointers in function arguments (or local variable pointers based on arguments) where the function is honoring a contract not to modify the pointed-to data. The const keyword helps ensure that the function implementation respects the requirement not to modify (it requires special effort casting to get rid of const) and allows this requirement to propagate through multiple function calls.
  • For declaring compile-time constant tables (lookup tables, predefined permanent objects, etc.) which I want stored in a read-only section of the binary so they don't use extra physical resources at runtime.

I sometimes declare local variables const if I think it will assist the reader in understanding a function, but that's pretty rare.

陌若浮生 2024-08-11 04:23:35

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

void func()
{
    int y;

    // Do assertions
    assert(something);
    {
        int const x = 5;
        // Function body
     }
}

You can't initialize the const after declaration within the function body, but you can just open one block after your assertions:

void func()
{
    int y;

    // Do assertions
    assert(something);
    {
        int const x = 5;
        // Function body
     }
}
故人如初 2024-08-11 04:23:35

如果您正在谈论将定义分成

const int x = 2;

两部分:

const int x;

x = 2;

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

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

回应各种评论:

const int * p;

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

您可以声明

extern const int x;

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

If you are talking of splitting a definition

const int x = 2;

into two parts:

const int x;

x = 2;

I'm afraid that's not possible in C.

If I were you, I would try to make sure I understand the intent of the coding rules that you describe. I doubt sane coding rules would prevent initializing variables (even non-const variables).

In response to various comments:

const int * p;

is not a declaration of a const variable. It is a declaration of a non-const pointer variable to a const int.

You can declare

extern const int x;

but you can still not initialize x after having executed code, assertion checks, etc.

晚雾 2024-08-11 04:23:35

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

const int n = 0;

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

If you'd like to cast away const on the LHS, use this:

const int n = 0;

*((int*)&n) = 23;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文