реклама на сайте
подробности

 
 
> Область видимости enum, C
sigmaN
сообщение Oct 12 2009, 11:59
Сообщение #1


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



На сколько я понял, если в заголовочном файле определено что-то вроде
Код
enum packetTypes{ IDPacket, BlockPacket };
то пока не определена переменная типа packetTypes - никакой памяти никуда выделяться не будет? Т.е. это почти то-же, что и typedef, только объявили множество. ?
Также верно следующее:
1. Определить переменную(в .c/.h файле) так: enum packetTypes packetType; можно только при условии include того заголовочного файле, в котором определен packetTypes
2. В любом другом файле, в котором не было include заголовочного - я никаким образом не смогу добраться до packetTypes.
3. Под enum не выделяется память(в отличие от const).
4. Глобальная переменная, определенная как enum packetTypes packetType; может быть видна из другого файла посредством extern enum packetTypes packetType; при условии, что include сделан( и,таким образом packetTypes определен)
5. Можно ли определить static enum packetTypes packetType; и ограничить область видимости переменной одним файлом?(не вижу причин, почему это может не работать. Но всё-же спрошу)
6. тип enum предполагается int. Как в Си изменить его, скажем, на unsigned int или long?

Правильно ли я мыслю? Какие из этих утверждений верны, какие нет?

А ещё всегда хотелось иметь под рукой первоисточник. Стандарт Си(какой там щас актуален).
Если можно тоже ссылочку.

Спасибо.

P.S. Навеяно прочтением книги Ален И. Голуб - Правила программирования на Си и Си++ и осознанием того, что моя программа на Си выглядит ужасно и половина возможностей языка осталась "за кадром" smile.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 14)
Dima_G
сообщение Oct 12 2009, 12:20
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата
На сколько я понял, если в заголовочном файле определено что-то вроде
Код
enum packetTypes{ IDPacket, BlockPacket };
то пока не определена переменная типа packetTypes - никакой памяти никуда выделяться не будет? Т.е. это почти то-же, что и typedef, только объявили множество. ?


Да. Этим вы определяете тип данных, и множество значений этого типа. Переменную этого типа вы таким образом не объявляете.

Цитата
Также верно следующее:
1
* * *
5.

ДА

Цитата
6. тип enum предполагается int. Как в Си изменить его, скажем, на unsigned int или long?


Никак. Размер элемента enum всегда равен int
Go to the top of the page
 
+Quote Post
kurtis
сообщение Oct 12 2009, 12:40
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Цитата
3. Под enum не выделяется память(в отличие от const).

Под const тоже память выделяется не всегда:
Код
const unsigned char MAX_ROWS = 2;
будет полностью равнозначно
Код
#define MAX_ROWS 2

Только в первом случае, если где-то будет MAX_ROWS переопределено (ошибочно), то компилятор выразит свое негодование программистом, а в случае с #define сделает вид что ничего не заметил.
Это актуально для С++ и вроде актуально для С99 (для С89 вроде как нет).

Цитата
Ален И. Голуб - Правила программирования на Си и Си++

могу ошибаться, но книга ОЧЕНЬ старая и там многое устарело, особенно что касается С++.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Oct 12 2009, 12:41
Сообщение #4


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Ok. Сппсибо. Просто хотел уточнить для верности.

На сколько я знаю,
Код
const unsigned char MAX_ROWS = 2;
делает следующее:
Создаёт переменную с указанным типом и именем и инициализирует её указанным значением. Так-же, компилятор при этом внимательно следит, чтобы этой переменной ничего не присваивали и ругается, если обнаруживает такую ситуацию. Т.е. память выделяется.

Попытка "передефайнить" MAX_ROWS заново будет выдавать предупреждение(мой компилер делает это так). Не знаю как насчёт поределения
Код
int MAX_ROWS
где-то после...вот этого действительно заметить не сможет. Но оно и не страшно вроде как, потому что препроцессор ещё ДО компилятора уже выполнил подстановку и подставит куда нужно циферку 2(в нашем случае)... Но спору нет. Путаница получается.

Книга может быть и старая, но вот некоторые советы в ней, кажутся мне бессмертными smile.gif
В С++ пока не вникал, не знаю.....


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
kurtis
сообщение Oct 12 2009, 13:02
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 21-06-05
Пользователь №: 6 205



Цитата
Создаёт переменную с указанным типом и именем и инициализирует её указанным значением.

Ну как бы да, но если он встретит такой вот код (например)
Код
some_value = MAX_ROWS + 4;
то у него будут все основания подставить вместо MAX_ROWS его фактичесное значение (т.к. MAX_ROWS константа, и измениться никаким образом не может). И дополнительной памяти под переменную выделено не будет, каждый раз будет просто подставлятся значение переменной.

Цитата
Но оно и не страшно вроде как, потому что препроцессор ещё ДО компилятора уже выполнил подстановку и подставит куда нужно циферку 2(в нашем случае)

Препроцессор очень злая штука (ОЧЕНЬ ЗЛАЯ!!!). Если где-то в заголовках будет написано #define MAX_ROWS 2, а потом где-то по ошибке будет написано #define MAX_ROWS 4, то может получиться очень неоднозначная ситуация, когда будете думать что должно подставлятся 2, а на самом деле будет подставлятся 4.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 12 2009, 13:32
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(sigmaN @ Oct 12 2009, 14:59) *
6. тип enum предполагается int. Как в Си изменить его, скажем, на unsigned int или long?
Компиляторы обычно имеют галочку типа "выделять минимально необходимый тип". В gcc это -fshort-enums, у IAR такое поведение вообще единственно возможное ("если нужен тип больше, объявите в списке значение с достаточно большим значением").


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
dxp
сообщение Oct 12 2009, 13:52
Сообщение #7


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Dima_G @ Oct 12 2009, 19:20) *
Никак. Размер элемента enum всегда равен int

А разве это не implementation defined?

Цитата(sigmaN @ Oct 12 2009, 19:41) *
На сколько я знаю,
Код
const unsigned char MAX_ROWS = 2;
делает следующее:
Создаёт переменную с указанным типом и именем и инициализирует её указанным значением. Так-же, компилятор при этом внимательно следит, чтобы этой переменной ничего не присваивали и ругается, если обнаруживает такую ситуацию. Т.е. память выделяется.

В С компилятор обязан выделять под константы, объявленные указанным способом, память, т.к. по умолчанию глобальные объекты имеют внешнее связывание - т.е. на них могут быть ссылки из других единиц компиляции. В С++ константы по умолчанию имеют внутреннее связывание - т.е. область видимости такого объекта - scope данной единицы компиляции (файла), и любой вменяемый компилятор не будет под такие объекты выделять память.

Конечно, можно заставить компилятор выделить память путем взятия адреса константы либо объявив ее как extern - в последнем случае эта константа явно указана как имеющая внешнее связывание, что приводит ситуацию к той, что в С. И наоборот, в С можно привести поведение константы к С++ному - для этого надо объявить константу как static - это будет ++ная константа. Попробуйте объявить свою константу так. smile.gif


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Oct 12 2009, 14:21
Сообщение #8


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



ООоо, а про static к константе я как-то не подумал. Щас посмотрим выделит память или не выделит :-)


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
Палыч
сообщение Oct 12 2009, 14:32
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(sigmaN @ Oct 12 2009, 14:59) *
А ещё всегда хотелось иметь под рукой первоисточник.


http://www.onlinedisk.ru/file/239872/
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 12 2009, 14:35
Сообщение #10


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(sigmaN @ Oct 12 2009, 18:21) *
ООоо, а про static к константе я как-то не подумал. Щас посмотрим выделит память или не выделит :-)
А что смотреть? Если взятие адреса не происходит, то и в памяти её держать не нужно.
static const - есть правильная альтернатива define.
За исключением того, что другую константу нельзя инициализировать ей.
И ещё, очень красиво на замену define ложится безымянный enum. Вместо:
Код
#define SOMETHING1 1
#define SOMETHING2 2
#define SOMETHING3 3
используйте:
Код
enum
{
    SOMETHING1  = 1,
    SOMETHING2,
    SOMETHING3
};
Программировать надо на языке программирования, а не на языке препроцессора. ИМХО.
Конечно, есть целый класс задач, решающихся с использованием макросов (инициализация полей больших структур значениями по умолчанию например).
Но когда можно написать программу красиво и выразительно без использования директив препроцессора, то так и стоит поступать.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Oct 12 2009, 20:50
Сообщение #11


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Однако давно хотел спросить как это так?
Код
    static const int N = 4;
    static char buf[N];     //error: expression must have a constant value


Код
    #define    N    4
    static char buf[N];     //OK.


Код
    enum{N = 4};
    static char buf[N];     //OK.

Комментируем smile.gif
Компилю под TMS320F28335


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 12 2009, 22:44
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Может объяснение корявое, но я понимаю так.
Вы смешиваете два понятия константы. Константа как число и константа как переменная, не изменяющая нигде внутри единицы компиляции своего значения (объявленная с квалификатором const).
В вашем первом примере объявляются два независимых объекта компиляции. Но в момент объявления второго объекта ничего еще не известно о значении первого. Потому, что объявление и инициализация это два разных этапа компиляции. Объявление это выделение места в памяти, а инициализация это присвоение значения уже имеющемуся объекту, под который память уже выделена. Поэтому в стандарте Си имеется явное ограничение на то, что в момент объявления массива его размер должен быть известен (задан константой-числом).
Еще про квалификатор const. Другое дело, что компилятор в процессе оптимизации (при повторных проходах) может выкинуть константный объект, подставив его значение "по месту". Но вначале (при первом проходе) компилятор все равно обязан выделить память при объявлении этого константного объекта. Просто вы об этом не (у)знаете.
Ну а два последних ваших примера дают всего лишь подстановку на этапе работы препроцессора, еще до этапа компиляции. Выражения эквивалентны
Код
static char buf[4];
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Oct 13 2009, 00:36
Сообщение #13


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Цитата
static const - есть правильная альтернатива define.
а в таком простом деле он не позволяет выполнить то, что позволяет #define smile.gif
Тут нужен enum. Но там, где значение выходит за границы int - enum не прокатывает и приходится использовать const и принципиально правильной назвать нельзя ни одну из альтернатив.

rezident, с Вашими рассуждениями нельзя не согласиться. Однако, немного не логично как-то. Если const уже const и его нельзя менять по определению, то почему-бы компилятору не выполнить ту-же подстановку его инициализирующего значения и просто не скомпилить код smile.gif Нужно будет написать в SO/IEC, пусть правят biggrin.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 13 2009, 00:51
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(sigmaN @ Oct 13 2009, 06:36) *
Это я к тому, что а на таком простом деле он не позволяет выполнить то, что позволяет #define smile.gif
ЯВУ он потому и высокого уровня, что позволяет весьма просто объяснить компилятору то, что вы от него хотите. Однако компилятор это тоже программа, которая не может "домысливать" за человека и поэтому работает в рамках описанных правил и стандартов. Общеизвестно, что любая программа не умнее программиста, написавшего ее laughing.gif
Go to the top of the page
 
+Quote Post
dxp
сообщение Oct 13 2009, 02:35
Сообщение #15


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(sigmaN @ Oct 13 2009, 03:50) *
Комментируем smile.gif
Компилю под TMS320F28335

Включите С++ режим, и статиков никаких не понадобится, будет собираться и так. Никогда не понимал, зачем использовать С при наличии С++ (ситуации, когда заказчик требует или нужна мегапереносимость, т.е. есть платформы, для которых нет ++, хотя таких уже сегодня по пальцам можно пересчитать, понятны). Даже без всяких классов и прочих плюсатых вещей просто более разумное поведение компилятора в обсуждаемой и подобных (например, работа с enum) ситуациях в сочетании с такими мелочами, как объявление объекта непосредственно перед использованием, уже дает эффект и просто делает сам процесс написания программы более приятным занятием.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th July 2025 - 06:47
Рейтинг@Mail.ru


Страница сгенерированна за 0.0148 секунд с 7
ELECTRONIX ©2004-2016