Количество элементов в множестве (enum)
enum TERRAINS
{
UNKNOWN_TERRAIN = -1,
FOREST,
BASIN,
DESERT,
ROAD,
HOBITATION,
LEA,
DANGERZONE
};
Вопрос: Можно ли узнать сколько элеметов в данном перечислении, чем-нибудь вроде sizeof()?
Скажи пожалалуйста - а тебе зачем, ведь ты сам создаешь все
Вполне логичный вопрос.
Однако поскольку проект не проработан до конца, то в процессе его исполнения некоторые контанты и типы меняются.
//----------------------------------------------------------
// Имена файлов
//----------------------------------------------------------
const AnsiString GraphFiles[] =
{
"pics\\F5n5.bmp",
"pics\\F5n5nums.bmp",
"pics\\z.bmp",
"pics\\z3.bmp"
};
//----------------------------------------------------------
// Номера файлов
//----------------------------------------------------------
enum GraphFileNumbers
{
LEEFILE = 0,
LEEFILE2,
ZFACE,
ZFACER
};
const int GraphFilesNum = 4;
//----------------------------------------------------------
// Сообщения об ошибках
//----------------------------------------------------------
AnsiString ErrorMess[] =
{
"Нет файла поля!",
"Нет файла поля!",
"Нет файла zf!",
"Нет файла zfr!"
};
//----------------------------------------------------------
// Функуция проверки наличия всех необходимых файлов
//----------------------------------------------------------
void CheckRes()
{
for (int i=LEEFILE;i<GraphFilesNum;i++)
{
if (!FileExists(GraphFiles)) throw Exception(ErrorMess);
}
}
Как видно из кода, чтобы добавить какой-нибудь файл, необходимо изменить значение переменной GraphFilesNum.
Ну лень мне это делать, лень. К тому же мне кажется это излишним. Вот и ищу другой способ.
enum GraphFileNumbers
{
LEEFILE = 0,
LEEFILE2,
ZFACE,
ZFACER
};
const int GraphFilesNum = 4;
Если ты используешь перечисления без присвоений внутри (меняющих их порядок по умолчанию: от 0 и далее +1), то последний элемент и есть количество.
Например:
enum GraphFileNumbers
{
LEEFILE ,//= 0 - оно и так =0 - по умолчанию
LEEFILE2,
ZFACE,
ZFACER,
GraphFilesNum
};
Т.е. теперь ты всегда уверен, что GraphFilesNum и есть кол-во
Предположим у меня есть перечисление вида
enum TERRAINS
{
UNKNOWN_TERRAIN = -1,
FOREST,
BASIN,
DESERT,
ROAD,
HOBITATION,
LEA,
DANGERZONE
};
Вопрос: Можно ли узнать сколько элеметов в данном перечислении, чем-нибудь вроде sizeof()?
Нет, нельзя. Перечисление, вообще, не имеет "физического" представления, т.е. не занимает места, не имеет размера и т.д.
Что касаемо GraphFilesNum, то оно связано на мой взгляд с GraphFiles[], а не enum:
const int GraphFilesNum = sizeof(GraphFiles)/sizeof(GraphFiles[0]);
enum GraphFileNumbers
{
LEEFILE ,//= 0 - оно и так =0 - по умолчанию
LEEFILE2,
ZFACE,
ZFACER,
GraphFilesNum
};
Разумно.
Других вариантов нет?
Нет, нельзя. Перечисление, вообще, не имеет "физического" представления, т.е. не занимает места, не имеет размера и т.д.
Ага.
Что касаемо GraphFilesNum, то оно связано на мой взгляд с GraphFiles[], а не enum:
Резонно.
const int GraphFilesNum = sizeof(GraphFiles)/sizeof(GraphFiles[0]);
Проверил. Работает. Хотя с моей точки зрения не должно: длины названий файлов разные.
Разумно.
Других вариантов нет?
Этот не устраивает ? Или сомневаешься - вот кусок моего кода:
enum { cl_Screen=0, // фон экрана
....
....
cl_ErrorMsg, // сообщения об ошибках
cl_HotKeys, // @горячие@ клавиши
cl_ //
};
....
....
unsigned char Clrs[cl_];
Enumы хотя и могут именоваться, но не подвержены sizeof-у - их действительно нет во время исполнения - о них "знал" лишь компилятор...
Проверил. Работает. Хотя с моей точки зрения не должно: длины названий файлов разные.
Длины названий здесь не имеют значения.
GraphFiles[] - массив const AnsiString
sizeof(GraphFiles) - размер этого массива
sizeof(GraphFiles[0]) - размер элемента массива, т.е. sizeof(AnsiString).
Этот не устраивает? Или сомневаешься...
Да нет. Просто интересно есть ли другие решения.
Enumы хотя и могут именоваться, но не подвержены sizeof-у - их действительно нет во время исполнения - о них "знал" лишь компилятор...
Got it!
GraphFiles[] - массив const AnsiString
sizeof(GraphFiles) - размер этого массива
sizeof(GraphFiles[0]) - размер элемента массива, т.е. sizeof(AnsiString).
Это ясно. Однако не ясно почему AnsiString имеет такой странный размер: всего 4 байта?
Да еще вопрос:
Можно ли пробежаться по всем значениям перечисления enum в цикле, если они не составляют арифметическую последоватьность, вроде:
enum E
{
E1 = 0,
E2,
E3 = -3,
E4 = 102,
E5 = 8
};
?
Это ясно. Однако не ясно почему AnsiString имеет такой странный размер: всего 4 байта?
Размер класса определяется суммарным размером входящих в него членов данных с учетом выравнивания.
Т.о. получается, что AnsiString, видимо, имеет один такой член - указатель на строку.
Да еще вопрос:
Можно ли пробежаться по всем значениям перечисления enum в цикле, если они не составляют арифметическую последоватьность, вроде:
enum E
{
E1 = 0,
E2,
E3 = -3,
E4 = 102,
E5 = 8
};
?
Нет. Хотя, вопрос не совсем понятен.
Размер класса определяется суммарным размером входящих в него членов данных с учетом выравнивания.
Т.о. получается, что AnsiString, видимо, имеет один такой член - указатель на строку.
Т.е. допустим:
если данные занимают int x - байт, а память квантуется по int i байт, то в случае если x%i!=0, то под эти данные выделится память размером (x/i)*(i+1)?
Я такого не замечал. Можно ссылочку кинуть на тему этого таинственного выравнивания?
Нет. Хотя, вопрос не совсем понятен.
Ну например написать что-нибудь вроде:
for(int i=E.begin(); i!=E.end(); i++)
{
Check(i);
}
Т.е. допустим:
если данные занимают int x - байт, а память квантуется по int i байт, то в случае если x%i!=0, то под эти данные выделится память размером (x/i)*(i+1)?
Я такого не замечал. Можно ссылочку кинуть на тему этого таинственного выравнивания?
Посмотри опции компилятора. Для VC++ это /Zp.
А также #pragma pack
Ну например написать что-нибудь вроде:
for(int i=E.begin(); i!=E.end(); i++)
{
Check(i);
}
Нет. Нельзя. Для этого используются массивы, и контейнеры. У перечислений другой смысл.
Enumы хотя и могут именоваться, но не подвержены sizeof-у - их действительно нет во время исполнения - о них "знал" лишь компилятор...
Кстати, sizeof() в данном случае тоже вычисляется еще при компиляции программы.
Кстати, sizeof() в данном случае тоже вычисляется еще при компиляции программы.
он м.б. и вычисляется - но как ?
проверь сам на практике (в отладчике):
enum E
{
E1,
E2,
E3,
E4,
E5
};
...
int e=sizeof(E);
...
- посмотри чему равно е...
Кстати, sizeof() в данном случае тоже вычисляется еще при компиляции программы.
sizeof всегда вычисляется при компиляции
Кстати, sizeof можно писать и без скобок:
int e = sizeof E;
он м.б. и вычисляется - но как ?
проверь сам на практике (в отладчике):
enum E
{
E1,
E2,
E3,
E4,
E5
};
...
int e=sizeof(E);
...
- посмотри чему равно е...
sizeof для enum это размерность наименьшего (по размерности) типа, который может содержать наибольшее значение из enum. Но этот тип по размерности не больше int.
Может, коряво сказал, но в кратце sizeof для enum будет 1, 2 или 4, в зависимости от разрядности максимального значения.
Правда, это было действительно для 32-битных архитектур. Возможно, что для 64-битных sizeof может быть и 8.
sizeof всегда вычисляется при компиляции
Действительно, так и есть. Я вчера в кое-какие доки заглянул чтобы уточнить.