Хотя это класс, использование BitArray
похоже на способ наименее изобретать колесо. Если вы на самом деле не настаиваете на производительности, это самый простой вариант. (На указатели можно ссылаться на оператор []
.)
Не изменяя подпись? Добавьте элемент сигнальной метки. Для массивов символов а именно, это могло быть завершение пустого указателя '\0'
, который используется для стандартных струн до.
void doSomething(char charArray[])
{
char* p = charArray;
for (; *p != '\0'; ++p)
{
// if '\0' happens to be valid data for your app,
// then you can (maybe) use some other value as
// sentinel
}
int arraySize = p - charArray;
// now we know the array size, so we can do some thing
}
, Конечно, затем Ваш массив сам не может содержать элемент сигнальной метки как содержание. Для других видов (т.е. несимвол) массивы, это могло быть любое значение, которое не является допустимыми данными. Если никакое такое значение не существует, то этот метод не работает.
, Кроме того, это требует сотрудничества на стороне вызывающего абонента. Действительно необходимо удостовериться, что вызывающая сторона резервирует массив arraySize + 1
элементы, и всегда наборы элемент сигнальной метки.
Однако, если Вы действительно не можете изменить подпись, Ваши опции скорее ограничены.
Вы, как гарантируют, получите 4 в 32-разрядном ПК, и это - корректный ответ. из-за причины объяснил здесь и здесь . Короткий ответ, Вы на самом деле тестируете sizeof указатель, а не массив, потому что "массив неявно преобразовывается, или затухания, в указатель. Указатель, увы, не хранит размер массива; это даже не говорит Вам, что рассматриваемая переменная является массивом".
Теперь, когда Вы используете C++, повышение:: массив является лучшим выбором, чем необработанные массивы. Поскольку это - объект, Вы не освободите dimention информацию теперь.
Для функции для знания количества объектов в массиве, который был передан ему необходимо сделать одну из двух вещей:
можно сделать последнего несколькими способами:
Это - на самом деле больше C, чем C++, в C++ Вы, вероятно, использовали бы станд.:: вектор. Однако в C нет никакого способа знать размер массива. Компиляция позволит Вам делать sizeof, если массив был объявлен в текущей области, и только если это было явно объявлено с размером ( РЕДАКТИРОВАНИЕ: и "с размером", я подразумеваю, что он был или объявлен с целочисленным размером или инициализирован в объявлении, в противоположность тому, чтобы быть переданным в качестве параметра, спасибо за downvote).
общее решение в C состоит в том, чтобы передать второй параметр, описывающий число элементов в массиве.
РЕДАКТИРОВАНИЕ:
Извините, пропустил часть о не желании изменить сигнатуру метода. Затем нет никакого решения за исключением описанного другими также, если существуют некоторые данные, которые не позволяются в массиве, они могут использоваться в качестве разделителя (0 в струнах до,-1 также довольно распространено, но они зависят от Вашего фактического типа данных, предполагая, что массив символов является гипотетическим)
Это на самом деле раньше было довольно общим решением для передачи длины в первом элементе массива. Этот вид структуры часто называют BSTR
(для “BASIC string”), даже при том, что это также обозначило отличающийся (но подобный) типы.
преимущество перед принятым решением состоит в том, что определение длины с помощью сигнальной метки является медленным для больших строк. Недостаток, очевидно, что это - взлом довольно низкого уровня, который не уважает ни типов, ни структуры.
В форме, данной ниже его также только, работает на строки длины < = 255. Однако это может легко быть расширено путем хранения длины больше чем в одном байте.
void doSomething(char* charArray)
{
// Cast unnecessary but I prefer explicit type conversions.
std::size_t length = static_cast<std::size_t>(static_cast<unsigned char>(charArray[0]));
// … do something.
}
В целом при работе с C или C++ низкого уровня, Вы могли бы полагать, что переквалификация Вашего мозга никогда не рассмотрела параметры массива записи к функции, потому что компилятор C будет всегда рассматривать их как указатели так или иначе. В сущности путем ввода тех квадратных скобок Вы дурачите себя в размышлении, что действительный массив передается, вместе с информацией о размере. В действительности в C можно только передать указатели. Функция
void foo(char a[])
{
// Do something...
}
, с точки зрения компилятора C, точно эквивалентного:
void foo(char * a)
{
// Do something
}
и очевидно что nekkid символьный указатель не содержит информации о длине.
, Если Вы застреваете в углу и не можете изменить функциональную подпись, рассмотреть использование префикса длины, как предложено выше. Непортативный, но совместимый взлом должен указать, что длина массива в size_t поле расположилась прежде массив, что-то вроде этого:
void foo(char * a)
{
int cplusplus_len = reinterpret_cast<std::size_t *>(a)[-1];
int c_len = ((size_t *)a)[-1];
}
, Очевидно, Ваша вызывающая сторона должна создать массивы соответствующим способом прежде, чем передать их нечто.
, Само собой разумеется, это - ужасный взлом, но этот прием может выйти из проблемы в повышении.
Используйте шаблоны. Это технически не соответствует Вашим критериям, потому что это изменяет подпись, но код вызова не должен быть изменен.
void doSomething(char charArray[], size_t size)
{
// do stuff here
}
template<size_t N>
inline void doSomething(char (&charArray)[N])
{
doSomething(charArray, N);
}
Эта техника используется Microsoft Безопасные функции CRT и STLSoft's шаблон класса array_proxy .
Вы не можете определить размер от charArray
один. Та информация автоматически не передается функции.
, Конечно, если это - завершенная пустым указателем строка, можно использовать strlen()
, но Вы уже, вероятно, рассмотрели это!
Рассматривают передачу std::vector<char>
& параметр или пара указателей или указателя плюс параметр размера.