2014-02-03 5 views
0

Итак, у меня есть структура C++, у которой есть статический массив в качестве члена, и я хочу запросить его размер в конструкторе. Как я понял из этой статьи http://msdn.microsoft.com/en-us/library/4s7x1k91(VS.71).aspx, sizeof можно применить к статическому массиву, чтобы найти размер (в байтах) всего массива, а не только его тип. Однако, когда я делаю sizeof() на члене, он дает мне 4 (размер указателя) вместо размера массива. Вот контекст (тривиальный):sizeof статический член массива возвращает размер указателя, а не массив

struct A 
{ 
    char descirption[128]; 
    int value; 

    A(const char desc[], int val) 
    { 
     size_t charsToCopy = std::min(sizeof(description), sizeof(desc)); 
     memcpy(description, desc, charsToCopy); 
     value = val; 
    } 
} 

int main() 
{ 
    A instance("A description string", 1); 
    //now instance has a description string that says "A des" followed by garbage characters 
} 

Так как я могу получить размер массива члена полукокса?

Редактировать

Когда я поставил точку останова в компиляторе и инспектировать два значения sizeof(description) и sizeof(desc)sizeof(description) == 4 я вижу, и sizeof(desc) == 21. Отсюда моя путаница. Поскольку я передаю строковый литерал в конструктор, компилятор, кажется, с удовольствием сообщает мне реальный размер переданной строки. Может быть, это не так, если бы я назначил его переменной где-то, но прямо сейчас я Я пытаюсь отследить фундаментальную проблему: sizeof (some-member-static-array) дает мне что-то (относительно) бессмысленное.

Возможно ли, что sizeof выполняет какое-то измерение длины строки, потому что это массив символов?

+1

Знаете ли вы, что 'SizeOf (убывание)' всегда размер указателя, в качестве параметра 'Const символ убывание []' распадается на ' const char * desc'? – dyp

+1

'sizeof (description)' is fine, 'sizeof (desc)' - размер указателя char. Зачем использовать memcpy для копирования строки с нулевым завершением? –

+0

'sizeof (description) == 128',' sizeof (desc) == sizeof (void *) ', что еще вы ожидали? –

ответ

2

Это не тот член, который дает вам размер 4, это аргумент. Параметры типа массива в C++ преобразуются в указатели, так что ваш конструктор эквивалентен:

A(const char *desc, int val) 

Вот почему вы получаете размер указателя. Если вы действительно хотите использовать memcpy, вам придется передать длину вашего массива конструктору. Альтернативой является использование strncpy с максимальным количеством символов, установленным на 128.

Конечно, если вы использовали std::string, у вас не было бы этой проблемы.

+0

'strncpy' - это ужасная функция IMHO, она даже не гарантирует нулевой конец IIRC. – dyp

+0

@dyp Изменен «аргумент» на «параметр». –

+0

@ dyp Да, это ужасно. Требует вручную нулевое завершение последнего элемента массива. –

5

Несмотря на синтаксис, вы не можете передать массив по значению функции. Он распадается на указатель, не оставляя возможности найти размер; ваша функция эквивалентна

A(const char * desc, int val) 

так что sizeof(desc) является размер указателя.

Вы можете передать массив по ссылке, шаблонированиям функции размера массива:

template <size_t desc_size> 
A(const char (&desc)[desc_size], int val) 

Аргумент размера будет определен автоматически из аргумента функции, поэтому код прохождения строкового литерала будет работать как является.

Однако это работает только тогда, когда аргумент действительно представляет собой массив известных размеров; если вы хотите иметь дело с более общими строками, вам понадобится нечто более сложное. Как правило, удобнее использовать std::string для управления строками - он автоматически обрабатывает память и отслеживает размер для вас.

0

В этом конструкторе

A(const char desc[], int val) 
{ 
    size_t charsToCopy = std::min(sizeof(description), sizeof(desc)); 
    memcpy(description, desc, charsToCopy); 
    value = val; 
} 

параметр убывание неявно преобразуется компилятором в указатель на первый символ. Поскольку вы используете функцию std :: min, то очевидно, что sizeof (const char *) меньше sizeof (описание), и функция всегда будет возвращать 4 при условии, что размер указателя равен 4.

Кроме того, может случиться так, что приведенная строка не будет содержать оканчивающийся нуль после вызова memcpy. Я бы определил конструктору следующим образом

A(const char desc[], int val) 
{ 
    strncpy(description, desc, 128); 
    description[127] = '\0'; 
    value = val; 
} 

Кроме того, это хорошая идея, чтобы определить имя магического числа 128 либо с использованием enymerator или статическую константу.

Или, по крайней мере, вы можете написать следующим образом

A(const char desc[], int val) 
{ 
    const size_t N = sizeof(description); 
    strncpy(description, desc, N); 
    description[N-1] = '\0'; 
    value = val; 
} 
Смежные вопросы