Jump to content

    

Объявление глобального массива в C, длина которого константная переменная

Удивлен, что компилятор Keil с включенным стандартом C99 не выдал ошибки для такого кода:

 

const uint32_t N = 20;
static MyStruct_t Example[N];

 

В C в отличие от C++ const означает только read-only. Variable length array, появившийся в C99, применяется к локальным массивам в run-time.

Почему в моем случае нет ошибки для глобального массива? Странное поведение.

Share this post


Link to post
Share on other sites
Удивлен, что компилятор Keil с включенным стандартом C99 не выдал ошибки для такого кода:

 

const uint32_t N = 20;
static MyStruct_t Example[N];

 

В C в отличие от C++ const означает только read-only. Variable length array, появившийся в C99, применяется к локальным массивам в run-time.

Почему в моем случае нет ошибки для глобального массива? Странное поведение.

Странно, почему для вас этот код странный. Всё ок. Попробуйте изменить значение N в рантайме (в цикле N присвоить значение индекса/итерации цикла)--> будет ошибка.

Share this post


Link to post
Share on other sites
Странно, почему для вас этот код странный. Всё ок. Попробуйте изменить значение N в рантайме (в цикле N присвоить значение индекса/итерации цикла)--> будет ошибка.

Это я понимаю, что менять нельзя значение переменной. Более того, она должна быть объявлена const, иначе будет ошибка.

Почему тогда приводятся во всех книгах/примерах определения размеров массивов через define? Я имею в виду Си.

Наверное, час искал на форумах, но нигде не нашел примеров, чтобы определяли длину через const int. Мне самому именно такой метод нравится больше по сравнению с define. Сейчас задумался, правильно ли я понимаю стандарт и не допускаю ли ошибки. В C++ это обычная практика.

Share this post


Link to post
Share on other sites
. . . Попробуйте изменить значение N в рантайме (в цикле N присвоить значение индекса/итерации цикла)--> будет ошибка.

. . .

const с инициализацией размещается или во флеш, или реализуется оптимизатором как присваивание (если использование "разовое").Поэтому, если у компилятора есть совесть, до рантайма дойти не должно. Должна быть ошибка компилятора.

. . . . Почему тогда приводятся во всех книгах/примерах определения размеров массивов через define? . . .

Это не "определение", это "тупо подстановка" текста-цифров.

Через #define - тк далее в коде это значение может еще много-где понадобиться (и измениться),

а это удобно делать "централизованно" из одного #define.

------

А для "определения" - sizeof(). И такая конструкция вроде прокатывает:

int a, b; float c; char ms[100];
const int bf_size = sizeof(a) + sizeof(b) + sizeof(ms);

Share this post


Link to post
Share on other sites
Неплохо бы указывать. в каком компиляторе это у вас нет ошибки.

Arm Compiler 5.02 и 5.06.

P.S. Если выбрать C90, то тоже ошибок нет.

Share this post


Link to post
Share on other sites

мой gcc ругается на это сразу: "variable modified array 'MyArray' at file scopoe", если я ставлю (не структуту, просто int'овый массив), если я делаю глобальный массив int MyArray[int].

если же я включаю его в тело функции, то он сообщает, что "storage size of 'MyArray' isn't constant.

 

В общем-то так было всегда., сколько я ни мучаю gcc Так что либо смотрите на настройки компиляции, либо бегите от этого компилятора, как от огня. Какой бы он хороший ни был, если он не соответствует документации, то вы не можете ждать от него детерминированного результата.

Share this post


Link to post
Share on other sites

От GCC я другого не ожидал :) Тут нет вопросов. Задал тоже просто массив int'ов для Arm Compiler. Такая же фигня. Для успокоения совести выбрал C99 и добавил определение массива в main(), создался VLA. Для C90 это вызвало ошибку. То есть использование стандартов Си изменяется в настройках корректно. При этом как для C90, так и для C99 в случае глобального массива ни ворнингов, ни ошибок :( Может быть, кто-то еще повторит подобное. Вдруг я где-то ошибся.

Share this post


Link to post
Share on other sites

попробуйте компилировать с опцией --strict

Share this post


Link to post
Share on other sites
попробуйте компилировать с опцией --strict

Спасибо.

Для C90 совсем всё плохо, миллион ошибок сразу. Для C99 много ошибок при компиляции CMSIS следующего вида:

 

/core_cm3.c", line 58: Error:  #667: "asm" function is nonstandard
  __ASM uint32_t __get_PSP(void)

 

И еще неизвестно, сколько их будет дальше. Надо тогда попробовать сделать совсем маленький проектик.

 

UPD.: Задал опцию --strict только для файла main.c, сразу получил ошибку в моем массиве :)

 

Error:  #28: expression must have a constant value

 

А не подскажете, где-нибудь в документации Arm Compiler перечислены их фичи, отличные от стандарта?

 

В общем-то так было всегда., сколько я ни мучаю gcc Так что либо смотрите на настройки компиляции, либо бегите от этого компилятора, как от огня. Какой бы он хороший ни был, если он не соответствует документации, то вы не можете ждать от него детерминированного результата.

А вы с опциями --pedantic или --ansi компилируете? Хочу понять, в GCC изначально более жесткое соблюдение стандарта или нет...

Share this post


Link to post
Share on other sites

ARM Compiler armcc user guide. Есть на сайте ARM и Keil. Где что перечислено, не знаю. Я его только местами смотрел. Про --strict там конкретно написано, на что реагирует. Я его так и нашел по слову const.

Share this post


Link to post
Share on other sites
ARM Compiler armcc user guide. Есть на сайте ARM и Keil. Где что перечислено, не знаю. Я его только местами смотрел. Про --strict там конкретно написано, на что реагирует. Я его так и нашел по слову const.

Ага, пасиб. Guide этот знаю, завтра почитаю подробнее.

UPD.: Вот тут весь списочек: http://infocenter.arm.com/help/index.jsp?t...e/CHDGFDID.html

Только сходу свой случай не нашел.

Share this post


Link to post
Share on other sites
А вы с опциями --pedantic или --ansi компилируете? Хочу понять, в GCC изначально более жесткое соблюдение стандарта или нет...

Без опций.

Собственно, листинг моего Makefile:

CFLAGS=-g -Wall -O0

falsenoerror: falsenoerror.o

 

сам код:

#include <stdio.h>
#include <stdint.h>

const uint32_t N = 20;


int main () {
    static int MyArray[N];

    for (int i=0 i < N; i++) {
        MyArray[i] = i;
        print ("MyArray %d = %d", i, MyArray[i])
    }
    return 0;
}

 

Естественно, если вынести строку

static int MyArray[N];

из тела main, ничего не изменится.

Edited by one_eight_seven

Share this post


Link to post
Share on other sites

Спасибо большое. Опередили. Отыскал свои проекты под GCC, но вы раньше показали пример.

Читаю описания Arm Compiler, немало всяких дополнений там, отличных от стандарта.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this