2016-04-10 6 views
0

Итак, мой инструктор на C++ сказал нам в классе, что не существует функции для определения размера массива на C++, и я не был этому доволен. Я нашел здесь вопрос о stackoverflow, который дал этот бит кода (sizeof(array)/sizeof(*array)), и, хотя я не совсем понимаю его, я понимаю, что он берет общий объем памяти, выделенной для массива, и делит его на то, что я предполагаю, это распределение памяти по умолчанию его тип данных ... (???) Я решил заняться написанием функций (я в CS 111 - Основы 1) и написать функцию, которая вернула количество элементов в любом массиве, через который я его передал. Это то, что я написал:При передаче массива функции в C++, почему sizeof() не будет работать так же, как в основной функции?

#include <iostream> 
using namespace std; 

int length_of_array(int some_list[]) 
{ 
    // This only returns the integer 1 for some reason 
    return (sizeof(some_list)/sizeof(*some_list)); 
} 

int main() 
{ 
    // Declare and initialize an array with 15 elements 
    int num_list[] = {2,4,6,8,10,12,14,16,18,20,22,24,26,28,30}; 

    //Outputs what I assume is the total size in bytes of the array 
    cout << sizeof(num_list) << endl; 

    //Outputs what I assume to be size of memory set aside for each in element in an array 
    cout << sizeof(*num_list) << endl; 

    //This extrapolates array's number of elements 
    cout << "This is the output from direct coding in the\nint main function:\n" << 
      (sizeof(num_list)/sizeof(*num_list)) << endl; 

    //This function should return the value 15 but does not 
    int length = length_of_array(num_list); 

    cout << "This is the length of the array determined\n"; 
    cout << "by the length_of_array function:\n" << length << endl; 



    return 0; 
} 

Функция возвращает 1 независимо от того, что я делаю. Кто-нибудь, пожалуйста, дайте мне конкретное обходное решение C++ и объяснение того, как оно работает? Спасибо.

+0

функции C фактически не может принимать аргументы в виде массивов. Массивы вместо этого * распадаются * на указатели при передаче функций. См. Http://www.c-faq.com/aryptr/ – jamesdlin

+0

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

+0

Итак, если у него есть совершенно другой ответ, как он дублируется - может ли принятый ответ применяться к вопросу, который вы говорите, я дублировал? – Sinux1

ответ

2

Проблема здесь:

int length_of_array(int some_list[]); 

В основном, всякий раз, когда вы передаете массив в качестве аргумента функции, независимо от того, если вы передаете его как int arr[] или int arr[42], массив распадается на указатель (с ОДНОГО ИСКЛЮЧЕНИЕ, см ниже), поэтому выше подпись эквивалентна

int length_of_array(int* some_list); 

поэтому, конечно, делая sizeof(some_list)/sizeof(*some_list) вы получите соотношение между размером указателя массивом гнилых к и размером repres типа вставляя первый элемент. В вашем случае 1, как выглядит на вашей машине, размер указателя, вероятно, 4 байта (32 бита), такой же, как размер int.

Итак, мой инструктор C++ сказал нам в своем классе, что не существует функции для определения размера массива в C++, и я не был этому доволен.

ВАШ УЧИТЕЛЬ НЕПРАВИЛЬНО! Существует способ передачи массива по ссылке и получить его размер:

template<size_t N> 
int length_of_array(int (&arr)[N]) 
{ 
    std::cout << N << std::endl; // WORKS! 
    return N; 
} 
+0

Это не совсем так. Нет функции * для определения размера массива. Возможно, вы нашли * способ *, чтобы сделать это, но даже тогда он не будет работать для динамически распределенных массивов. Но во всяком случае, хороший трюк. Интересно, почему это не работает без ссылки? Поскольку он все равно распадается на указатель, хотя вы явно заявляете его размер? –

+0

@SergeyTachenov Технически вы правы, хотя я уверен, что учитель имел в виду, что независимо от того, как вы проходите массив, вы не можете получить его размер. При передаче его по ссылке функция фактически использует точный * тип * аргумента, который в этом случае является 'int [N]'. Например, если вы избавитесь от шаблона, но просто сделайте 'void f (int (& arr) [10])', то вы не сможете передавать массивы размером, отличным от '10'. Использование шаблона немного лучше, поскольку позволяет обнаруживать 'N'. – vsoftco

+0

@disk_Error Массивы немного сложны в C и C++.Они являются сильными типами, другими словами, 'int arr1 [10]' и 'int arr2 [20]' представляют два разных несовместимых типа. Но, передавая массив по значению функции, массив распадается на указатель, поэтому информация типа «стирается» и просто становится указателем. Исключение составляет при передаче по ссылке. 'int (& arr) [10]' означает, что 'arr' является ссылкой на массив' int [10] '. В моем коде я использовал шаблон, чтобы вы могли передавать любой размер (компилятор выведет 'N', так как знает полный тип массива). – vsoftco