powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Compile-time способ определения размера статического массива в количестве элементов.
25 сообщений из 36, страница 1 из 2
Compile-time способ определения размера статического массива в количестве элементов.
    #38070684
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Какой из compile-time способов определения размера в количестве элементов массива в статической памяти обычно используете?

1. Можно просто размер массива поделить на размер одного элемента, но это сработает и для обычного указателя, что не нужно:
#define lengthof(x) (sizeof(x) / sizeof((x)[0]))


2. Можно попробовать создать холостой массив ссылок на функцию принимающую на вход массив, обычный указатель уже не пройдет, как и пользовательский тип с определенным оператором индексирования operator[]
Макрос из Хрома:
Код: plaintext
1.
2.
3.
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define ARRAY_SIZE(array) (sizeof(ArraySizeHelper(array)))



Или с использованием буста:
Код: plaintext
1.
2.
3.
template <typename T, size_t N>
typename boost::add_reference<char[N]>::type ArraySizeHelper( T (&)[N] ) ;
#define ARRAY_SIZE(array) (sizeof(ArraySizeHelper(array)))




3. По действию тоже что и 2, или может чем-то отличается? Макрос из Уилсона, расширение STL:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
template <int N>
struct ss_array_size_struct {
    unsigned char c[N];
};
template <class T, int N>
ss_array_size_struct<N> const& ss_static_array_size(T (&)[N]);

#define STLSOFT_NUM_ELEMENTS(ar) sizeof(ss_static_array_size(ar).c)




4. Но что меня больше всего удивило, что никто не использует простую функцию без всяких макросов:
Код: plaintext
1.
template <typename T, size_t N> size_t arr_size(T (&)[N]) { return N; }



На фига эти дефайны и бусты. Или есть причины её не использовать?
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070697
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compile-time4. Но что меня больше всего удивило, что никто не использует простую функцию без всяких макросов:
Код: plaintext
1.
template <typename T, size_t N> size_t arr_size(T (&)[N]) { return N; }


На фига эти дефайны и бусты. Или есть причины её не использовать?почему никто? я использую, например. Тоже не понимаю, на фига все эти макросы нужны, в 21м то веке ))
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070722
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compile-timeКакой из compile-time способов определения размера в количестве элементов массива в статической памяти обычно используете?

1. Можно просто размер массива поделить на размер одного элемента, но это сработает и для обычного указателя, что не нужно:
#define lengthof(x) (sizeof(x) / sizeof((x)[0]))
Этот и только этот.

Все остальные предложенные методы чушь, глупость и гадость.
Нафига накручивать шаблоны на простой статический массив? А уж тянуть для этой цели буст это вообще уму не постижимо.
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070723
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
egorychCompile-time4. Но что меня больше всего удивило, что никто не использует простую функцию без всяких макросов:
Код: plaintext
1.
template <typename T, size_t N> size_t arr_size(T (&)[N]) { return N; }


На фига эти дефайны и бусты. Или есть причины её не использовать?почему никто? я использую, например. Тоже не понимаю, на фига все эти макросы нужны, в 21м то веке ))
Тут как я понял дело в том, что #define это constexpr, а такая функция - нет. И в MS VS 2012 ещё не запили само ключевое слово constexpr.

По этому в "умных книжках" и оупенсорсных проектах используют template и его ещё в #define оборачивают.

Для GCC:
http://stackoverflow.com/questions/6376000/how-does-this-array-size-template-work
Код: plaintext
1.
template <typename T, size_t N> constexpr size_t array_size(const T (&)[N]) { return N; }



Ну и привели ещё один извращенный вариант с decltype :)
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070725
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White OwlCompile-timeКакой из compile-time способов определения размера в количестве элементов массива в статической памяти обычно используете?

1. Можно просто размер массива поделить на размер одного элемента, но это сработает и для обычного указателя, что не нужно:
#define lengthof(x) (sizeof(x) / sizeof((x)[0]))
Этот и только этот.

Все остальные предложенные методы чушь, глупость и гадость.
Нафига накручивать шаблоны на простой статический массив? А уж тянуть для этой цели буст это вообще уму не постижимо.
Но он съест и обычный указатель, и пользовательский тип с определенным оператором индексирования.
А чем лучше накручивать #define вместо template?
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070733
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compile-timeТут как я понял дело в том, что #define это constexpr, а такая функция - нет.Ну если компилятор умный, то он в принципе, наверное, при включеной оптимизации, может быть и сможет превратить эту функцию в константу.

Compile-timeНо он съест и обычный указатель, и пользовательский тип с определенным оператором индексирования.Я не вижу проблемы в том, что дефайн на sizeof съест и обычный указатель. Этот дефайн тебе выдаст размер в единичку, что будет чистой правдой.

Compile-timeА чем лучше накручивать #define вместо template? Ну во первых, я немножко соврал в первом ответе. Такой дефайн я не использую никогда. Я всегда прямо по месту пишу формулу из sizeof(). В этом случае я всегда сразу вижу что в данном цикле for я работаю с размером именно статического массива а не какого-то там объекта или другого конструкта.
Во вторых, в трех первых твоих примерах кроме template ты вынужден использовать #define... И смысл тогда был template писать?
В третьих, ты заранее объявляешь что твоя функция возвращает size_t. Что не всегда равняется unsigned int, а размер массива обычно нужен в циклах, где как раз unsigned int и является предпочтительным типом. Конструкция основаная на sizeof() позволяет компилятору автоматически подбирать тип константы.
Ну и в конце-концов: я ненавижу templates. Считай это религией :)
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070734
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compile-timeА чем лучше накручивать #define вместо template?ничем, не слушай White Owl, когда он говорит про шаблоны и исключения - у него религиозное неприятие этих понятий.
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070736
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А что, простое
Код: sql
1.
2.
#define ARR_SIZE 100
int Array[ARR_SIZE];


ныне считается некошерным?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070737
Фотография ZyK_BotaN
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovА что, простое
Код: sql
1.
2.
#define ARR_SIZE 100
int Array[ARR_SIZE];



ныне считается некошерным?..почему тогда уж не константу объявить??
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070738
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovА что, простое
Код: sql
1.
2.
#define ARR_SIZE 100
int Array[ARR_SIZE];


ныне считается некошерным?..
Если у тебя один-единственный статический массив во всей программе, то можно и так жить.
А если у тебя два массива, или три.... Тогда ты будешь каждый раз сидеть и вспоминать какая из констант, к какому массиву относится. И молись чтобы не перепутать.
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070740
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White OwlCompile-timeТут как я понял дело в том, что #define это constexpr, а такая функция - нет.Ну если компилятор умный, то он в принципе, наверное, при включеной оптимизации, может быть и сможет превратить эту функцию в константу.
Да, GCC так и делает. Он хоть и знает constexpr и сам его подставляет.

White OwlCompile-timeНо он съест и обычный указатель, и пользовательский тип с определенным оператором индексирования.Я не вижу проблемы в том, что дефайн на sizeof съест и обычный указатель. Этот дефайн тебе выдаст размер в единичку, что будет чистой правдой.
Код: plaintext
1.
2.
3.
char *a = new char[20]; // а было: char a[20];
// некий код
(sizeof(a) / sizeof((a)[0])) == 4 // что неверно



Код: plaintext
1.
2.
3.
std::vector<char> a(20); // а было: char a[20];
// некий код
(sizeof(a) / sizeof((a)[0])) == 12 // что неверно



В случае с темплейтами - оно в compile-time выдаст ошибку, что и нужно.


White OwlCompile-timeА чем лучше накручивать #define вместо template? Ну во первых, я немножко соврал в первом ответе. Такой дефайн я не использую никогда. Я всегда прямо по месту пишу формулу из sizeof(). В этом случае я всегда сразу вижу что в данном цикле for я работаю с размером именно статического массива а не какого-то там объекта или другого конструкта.
Во вторых, в трех первых твоих примерах кроме template ты вынужден использовать #define... И смысл тогда был template писать?
В третьих, ты заранее объявляешь что твоя функция возвращает size_t. Что не всегда равняется unsigned int, а размер массива обычно нужен в циклах, где как раз unsigned int и является предпочтительным типом. Конструкция основаная на sizeof() позволяет компилятору автоматически подбирать тип константы.
Ну и в конце-концов: я ненавижу templates. Считай это религией :)
1. Ну использование ARRAY_SIZE/arr_size() тоже говорит, что 100% работа идет со статическим массивом, кстати в отличае от 1го варианта который съест и new char[] и vector.
2. Только второй вариант не ест ненужные типы и работает под GCC/MSVS
3. Т.к. это compile-time, то в любом случае все приведется к константе нужного типа. sizeof - так же возвращает size_t и так же приводит к нужному типу если это возможно.

И что вообще ничего из STL и даже умные указатели с контейнерами не используете из-за шаблонов? :)

PS насчет предпочтительного типа:
Насколько я помню переполнение unsigned - строго специфицировано, а signed - нет и тут компилятор может хорошо оптимизировать. Само же переполнение в любом случае логический крах, если иное явно не предусмотрено, и в случае signed - будет run-time exception, а в случае unsigned - все будет молча.
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070777
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlВ третьих, ты заранее объявляешь что твоя функция возвращает size_t. Что не всегда равняется unsigned int, а размер массива обычно нужен в циклах, где как раз unsigned int и является предпочтительным типом.
С какого перепугу в цикле unsigned int предпочтительнее чем size_t?
size_t - специально предназначен для индексов, размеров массивов и т.д.
А unsigned int не на всех платформах даже может вместить размер объекта в памяти.
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070908
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovА что, простое
Код: sql
1.
2.
#define ARR_SIZE 100
int Array[ARR_SIZE];


ныне считается некошерным?..
потому что часто удобно писать вот так:
Код: plaintext
1.
int arr[] = { 0, 1, 2, 3 };
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38070986
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вообще для циклов по коллекции будет следующая конструкция:
Код: plaintext
1.
for(auto i: a) std::cout << "a[" << i << "] = " << a[i] << std::endl;


Правда в GCC 4.5.1 она не работает, а в MSVS 2012 почему-то начинает с индекса i =1 для массивов, а для std::vector начинает с i = 0, но не инкрементирует его :)

А вот это скорее понадобится для следующего:
Код: plaintext
1.
2.
3.
4.
5.
template <typename T, size_t N> constexpr size_t array_size(const T (&)[N]) { return N; }
char a[] = {1, 2, 3, 4, 5, 6};

char b[array_size(a)];
char c[array_size(a) * 2];



Но ничего из этого сообщения в MSVS пока не работает :)
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071033
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compile-time,


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <boost/range.hpp>
...
char a1[] = "123";
char a2[boost::size(a1)];
cout << boost::size(a1) << endl; // 4
char* p1 = a1;
//cout << boost::size(p1) << endl; // compile error
int a3[] = {1, 2, 3};
cout << boost::size(a3) << endl; // 3
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071034
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну и цикл по массиву, если уж зашла речь:
Код: plaintext
1.
2.
3.
4.
5.
6.
char a1[] = "123";
BOOST_FOREACH(char c, boost::as_array(a1)) {}  // as_array нужен только для массивов char[] для устранения двойной трактовки строка/массив

int a3[] = {1, 2, 3};
BOOST_FOREACH(int c, boost::as_array(a3)) {}
BOOST_FOREACH(int c, a3) {}
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071048
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyCompile-time,


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <boost/range.hpp>
...
char a1[] = "123";
char a2[boost::size(a1)];
cout << boost::size(a1) << endl; // 4
char* p1 = a1;
//cout << boost::size(p1) << endl; // compile error
int a3[] = {1, 2, 3};
cout << boost::size(a3) << endl; // 3


Не знал. Самое простое :)

Но вот в MSVS оно не constexpr, т.е. на этой строчке загинается: char a2[boost::size(a1)];
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071052
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyНу и цикл по массиву, если уж зашла речь:
Код: plaintext
1.
2.
3.
4.
5.
6.
char a1[] = "123";
BOOST_FOREACH(char c, boost::as_array(a1)) {}  // as_array нужен только для массивов char[] для устранения двойной трактовки строка/массив

int a3[] = {1, 2, 3};
BOOST_FOREACH(int c, boost::as_array(a3)) {}
BOOST_FOREACH(int c, a3) {}


Это как раз то, что в новом стандарте for(auto c : a)?
Кстати, а в бустовом варианте и в новом стандарте стандарте:
1. индекс всегда начинается с 0?
2. нельзя идти по массиву с конца или с шагом большим 1?
3. нужен as_array для устранения двойной трактовки?
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071179
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compile-timeЭто как раз то, что в новом стандарте for(auto c : a)?
Кстати, а в бустовом варианте и в новом стандарте стандарте:
1. индекс всегда начинается с 0?
2. нельзя идти по массиву с конца или с шагом большим 1?
3. нужен as_array для устранения двойной трактовки?
1. Если индекс начинается не с 0, то это не С++, а паскаль какой-то - ересь короче :)
2. Не в курсе
3. as_array это бустовское. Как в c++11 - не знаю


То что VS не поддерживает boost::size() в качестве размера массива, это плохо и странно. Потому что gcc с выключенным C++11 - поддерживает.
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071191
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyCompile-timeЭто как раз то, что в новом стандарте for(auto c : a)?
Кстати, а в бустовом варианте и в новом стандарте стандарте:
1. индекс всегда начинается с 0?
2. нельзя идти по массиву с конца или с шагом большим 1?
3. нужен as_array для устранения двойной трактовки?
1. Если индекс начинается не с 0, то это не С++, а паскаль какой-то - ересь короче :)
2. Не в курсе
3. as_array это бустовское. Как в c++11 - не знаю


То что VS не поддерживает boost::size() в качестве размера массива, это плохо и странно. Потому что gcc с выключенным C++11 - поддерживает.
1. В MSVS12 цикл for(auto i: v) начинается с 1 для массивов, и не инкрементиться для векторов, спрашивается на фига его вообще там сделали :) Или может я чего не понял.

Да я надеялся, что уж VS12 будет держать и constexpr и соответственно boost::size(), но нет.
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071218
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compile-time1. В MSVS12 цикл for(auto i: v) начинается с 1 для массивов, и не инкрементиться для векторов, спрашивается на фига его вообще там сделали :) Или может я чего не понял.

Это уж слишком явный баг компилятора.
Ну или "чего не понял" :)
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071288
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Compile-time
Код: plaintext
1.
2.
3.
char *a = new char[20]; // а было: char a[20];
// некий код
(sizeof(a) / sizeof((a)[0])) == 4 // что неверно

А почему это "неверно"? Что просил, то и получил. Не надо работать с указателями как со статическими массивами и все.

Compile-time
Код: plaintext
1.
2.
3.
std::vector<char> a(20); // а было: char a[20];
// некий код
(sizeof(a) / sizeof((a)[0])) == 12 // что неверно


В случае с темплейтами - оно в compile-time выдаст ошибку, что и нужно.Ты не просто стреляешь себе в ногу, ты ее еще при этом обливаешь горящим бензином и смачиваешь кислотой.
Не я где-то наверное могу понять что против идиотского кода хотелось бы иметь защиту, но уж доводить до абсурда то зачем? Ты что не знаешь где у тебя статический массив в программе, где динамический а где класс? Ну тогда да, тогда тебе действительно надо запретить пользоваться sizeof().


Anatoly MoskovskyС какого перепугу в цикле unsigned int предпочтительнее чем size_t?
size_t - специально предназначен для индексов, размеров массивов и т.д.
А unsigned int не на всех платформах даже может вместить размер объекта в памяти.Если uint меньше чем size_t то ты прав. А если наоборот - то не прав :) Адресное пространство может быть меньше чем вместимость регистра. И хотя таких платформ сейчас не очень много, но...
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071296
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
White OwlЕсли uint меньше чем size_t то ты прав. А если наоборот - то не прав :) Адресное пространство может быть меньше чем вместимость регистра. И хотя таких платформ сейчас не очень много, но...
Причем тут размер регистров.
По стандарту гарантируется что size_t вмещает любой адрес на данной платформе.
А для int вообще по сути никаких гарантий не предоставляется кроме того, что он не меньше чем short.
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071307
Compile-time
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
White OwlCompile-time
Код: plaintext
1.
2.
3.
char *a = new char[20]; // а было: char a[20];
// некий код
(sizeof(a) / sizeof((a)[0])) == 4 // что неверно

А почему это "неверно"? Что просил, то и получил. Не надо работать с указателями как со статическими массивами и все.

Compile-time
Код: plaintext
1.
2.
3.
std::vector<char> a(20); // а было: char a[20];
// некий код
(sizeof(a) / sizeof((a)[0])) == 12 // что неверно


В случае с темплейтами - оно в compile-time выдаст ошибку, что и нужно.Ты не просто стреляешь себе в ногу, ты ее еще при этом обливаешь горящим бензином и смачиваешь кислотой.
Не я где-то наверное могу понять что против идиотского кода хотелось бы иметь защиту, но уж доводить до абсурда то зачем? Ты что не знаешь где у тебя статический массив в программе, где динамический а где класс? Ну тогда да, тогда тебе действительно надо запретить пользоваться sizeof().

Может это удивительно, но я пишу код не только для себя. И мой код могут легко читать и править другие люди.
Считаете никогда не может возникнуть необходимость изменить статический массив на динамический или на вектор?
...
Рейтинг: 0 / 0
Compile-time способ определения размера статического массива в количестве элементов.
    #38071356
White Owl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyWhite OwlЕсли uint меньше чем size_t то ты прав. А если наоборот - то не прав :) Адресное пространство может быть меньше чем вместимость регистра. И хотя таких платформ сейчас не очень много, но...
Причем тут размер регистров.
По стандарту гарантируется что size_t вмещает любой адрес на данной платформе.
А для int вообще по сути никаких гарантий не предоставляется кроме того, что он не меньше чем short.Ну и? Сам же уже ответил на вопрос. Повторяю: размер адреса не обязан совпадать с размером регистра. Считать одним целым регистром быстрее чем половинкой или двумя регистрами, верно? Поэтому использовать тип данных близкий к размеру регистра в качестве счетчиков лучше чем тип данных совпадающий с размером адреса.

Compile-timeСчитаете никогда не может возникнуть необходимость изменить статический массив на динамический или на вектор? В моей практике такого не случалось. Статические массивы это очень редкие зверьки с очень ограниченной областью применения. Обычно они живут в пределах одного модуля или даже одной функции и отследить все случаи использования не представляет никакого труда.
...
Рейтинг: 0 / 0
25 сообщений из 36, страница 1 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Compile-time способ определения размера статического массива в количестве элементов.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]