Передача массива как параметр функции в C++

Хотя это класс, использование BitArray похоже на способ наименее изобретать колесо. Если вы на самом деле не настаиваете на производительности, это самый простой вариант. (На указатели можно ссылаться на оператор [].)

18
задан Shog9 24 May 2009 в 06:22
поделиться

9 ответов

Не изменяя подпись? Добавьте элемент сигнальной метки. Для массивов символов а именно, это могло быть завершение пустого указателя '\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 элементы, и всегда наборы элемент сигнальной метки.

Однако, если Вы действительно не можете изменить подпись, Ваши опции скорее ограничены.

24
ответ дан 30 November 2019 в 05:44
поделиться

Вы, как гарантируют, получите 4 в 32-разрядном ПК, и это - корректный ответ. из-за причины объяснил здесь и здесь . Короткий ответ, Вы на самом деле тестируете sizeof указатель, а не массив, потому что "массив неявно преобразовывается, или затухания, в указатель. Указатель, увы, не хранит размер массива; это даже не говорит Вам, что рассматриваемая переменная является массивом".

Теперь, когда Вы используете C++, повышение:: массив является лучшим выбором, чем необработанные массивы. Поскольку это - объект, Вы не освободите dimention информацию теперь.

-1
ответ дан 30 November 2019 в 05:44
поделиться

Для функции для знания количества объектов в массиве, который был передан ему необходимо сделать одну из двух вещей:

  1. Передача в параметре размера
  2. Помещенный информация о размере в массив так или иначе.

можно сделать последнего несколькими способами:

  • Оконечный это с ПУСТЫМ УКАЗАТЕЛЕМ или некоторой другой сигнальной меткой, которая не произойдет в нормальных данных.
  • хранят количество объекта в первой записи, если массив содержит числа
  • , хранят указатель на последнюю запись, если массив содержит указатели
1
ответ дан 30 November 2019 в 05:44
поделиться

Это - на самом деле больше C, чем C++, в C++ Вы, вероятно, использовали бы станд.:: вектор. Однако в C нет никакого способа знать размер массива. Компиляция позволит Вам делать sizeof, если массив был объявлен в текущей области, и только если это было явно объявлено с размером ( РЕДАКТИРОВАНИЕ: и "с размером", я подразумеваю, что он был или объявлен с целочисленным размером или инициализирован в объявлении, в противоположность тому, чтобы быть переданным в качестве параметра, спасибо за downvote).

общее решение в C состоит в том, чтобы передать второй параметр, описывающий число элементов в массиве.

РЕДАКТИРОВАНИЕ:
Извините, пропустил часть о не желании изменить сигнатуру метода. Затем нет никакого решения за исключением описанного другими также, если существуют некоторые данные, которые не позволяются в массиве, они могут использоваться в качестве разделителя (0 в струнах до,-1 также довольно распространено, но они зависят от Вашего фактического типа данных, предполагая, что массив символов является гипотетическим)

2
ответ дан 30 November 2019 в 05:44
поделиться

если бы это - nullterminated, strlen () работал бы.

4
ответ дан 30 November 2019 в 05:44
поделиться

Это на самом деле раньше было довольно общим решением для передачи длины в первом элементе массива. Этот вид структуры часто называют 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.
}
6
ответ дан 30 November 2019 в 05:44
поделиться

В целом при работе с 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];
}

, Очевидно, Ваша вызывающая сторона должна создать массивы соответствующим способом прежде, чем передать их нечто.

, Само собой разумеется, это - ужасный взлом, но этот прием может выйти из проблемы в повышении.

6
ответ дан 30 November 2019 в 05:44
поделиться

Используйте шаблоны. Это технически не соответствует Вашим критериям, потому что это изменяет подпись, но код вызова не должен быть изменен.

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 .

38
ответ дан 30 November 2019 в 05:44
поделиться

Вы не можете определить размер от charArray один. Та информация автоматически не передается функции.

, Конечно, если это - завершенная пустым указателем строка, можно использовать strlen(), но Вы уже, вероятно, рассмотрели это!

Рассматривают передачу std::vector<char> & параметр или пара указателей или указателя плюс параметр размера.

2
ответ дан 30 November 2019 в 05:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: