Перейти к содержанию
    

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

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

 

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

 

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Удивлен, что компилятор 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 присвоить значение индекса/итерации цикла)--> будет ошибка.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

. . . Попробуйте изменить значение 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);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Неплохо бы указывать. в каком компиляторе это у вас нет ошибки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Неплохо бы указывать. в каком компиляторе это у вас нет ошибки.

Arm Compiler 5.02 и 5.06.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

попробуйте компилировать с опцией --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 изначально более жесткое соблюдение стандарта или нет...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вы с опциями --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, ничего не изменится.

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...