C: поведение ключевого слова const - PullRequest
7 голосов
/ 13 сентября 2009

Мне сказали, что если я кодирую в ANSI-C, чтобы объявить в порядке, что переменные будут использоваться, утверждать, что указатели не являются нулевыми, и что индексы находятся в пределах границ, и инициализировать непосредственно перед использованием переменная.

Если я объявляю const, могу ли я инициализировать его после блока утверждений и кода? В Java окончательная инициализация должна происходить при объявлении, но является ли она последовательной в реализациях ANSI-C, чтобы я мог инициализировать const один раз, но не обязательно во время объявления?

Ответы [ 7 ]

9 голосов
/ 13 сентября 2009

Компилятор 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 после блока утверждений и кода. Переносимость ANSI C 1999 года остается проблемой.

Обходной путь для C89 состоит в том, чтобы заметить, что правила для объявлений, предшествующих коду, работают в области блока, а не в области функции, поэтому вы можете сделать это:

#include<stdio.h>

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

    {
        const int x = 10;

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

    return 0;
}
3 голосов
/ 13 сентября 2009

Имейте в виду, что даже в 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 голосов
/ 13 сентября 2009

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 голосов
/ 08 июля 2010

Если не считать области видимости и методов объявления C99, показанных другими, ответ - нет; Вы не можете отложить инициализацию переменной const. В любом случае, const не очень полезен для локальных переменных. Основные времена, когда я использую ключевое слово const в C:

  • Указатели в аргументах функции (или указатели на локальные переменные, основанные на аргументах), где функция выполняет контракт, чтобы не изменять указанные данные. Ключевое слово const помогает гарантировать, что реализация функции соблюдает требование не изменять (оно требует особых усилий приведения, чтобы избавиться от const) и позволяет этому требованию распространяться через несколько вызовов функций.
  • Для объявления константных таблиц времени компиляции (справочных таблиц, предопределенных постоянных объектов и т. Д.), Которые я хочу хранить в секции только для чтения двоичного файла, чтобы они не использовали дополнительные физические ресурсы во время выполнения.

Я иногда объявляю локальные переменные const, если думаю, что это поможет читателю понять функцию, но это довольно редко.

2 голосов
/ 13 сентября 2009

Вы не можете инициализировать const после объявления в теле функции, но вы можете просто открыть один блок после ваших утверждений:

void func()
{
    int y;
    //do assertions
    assert(something);
    {
        int const x = 5;
        // function body
     }
}
1 голос
/ 13 сентября 2009

Если вы говорите о разделении определения

const int x = 2;

на две части:

const int x;

x=2;

Боюсь, это невозможно в C.

На вашем месте я бы постарался понять смысл правил кодирования, которые вы описываете. Я сомневаюсь, что нормальные правила кодирования предотвратят инициализацию переменных (даже неконстантных).

В ответ на различные комментарии:

const int * p;

НЕ является объявлением константной переменной. Это объявление неконстантной переменной-указателя на const int.

Вы можете объявить

extern const int x;

но вы все равно не можете инициализировать x после выполнения кода, проверки утверждений, ...

0 голосов
/ 10 июня 2011

Если вы хотите выбросить const на LHS, как насчет этого?

const int n = 0;

*((int*)&n) = 23;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...