2015-03-03 3 views
0

Я новичок в C/C++ и узнаю о массивах. Я только что закончил чтение о передаче массивов в функции, и я пытаюсь его реализовать. Я начинаю с массива x[] = "Hello, который, конечно, имеет sizeof() 6. Но по какой-то причине, когда я передаю его своей функции listElements(char arr[]), я получаю sizeof(arr), равный 4. Почему мой массив обрезается вот так?C++ Array Pass to Function отключается

Кроме того, sizeof(char) на мой компилятор 1.

#include <iostream> 
using namespace std; 

void listElements(char[]); 

int main(){ 
    char x[] = "Hello"; 
    cout << sizeof(x) << endl; // 6 
    listElements(x); 
    cin >> x[0]; 
    return 0; 
} 

void listElements(char arr[]){ 
    cout << "Size of arr: " << sizeof(arr) << endl; // 4 <--- why is this 4? 
    cout << "Size of char: " << sizeof(char) << endl; // 1 
    for (int j = 0; j < (sizeof(arr)/sizeof(char)); j++){ 
     cout << arr[j] << endl; 
    } 
    return; 
} 
+3

Массивы распадаются на * указатели *, поэтому 'sizeof (arr)' в функции - это размер указателя, а не массив, который вы передаете функции. Используйте 'strlen' для получения длины строки. Или, поскольку вы программируете на C++, вместо этого используйте ['std :: string'] (http://en.cppreference.com/w/cpp/string/basic_string). –

+1

sizeof (char) is * always * 1. – ryanpattison

+0

см. [Почему компиляторы C и C++ допускают длину массива в сигнатурах функций, когда они никогда не применяются] (http://stackoverflow.com/questions/22677415/why-do-do- c-and-c-compilers-allow-array-length-in-function-signature-when-they) –

ответ

7

Если вы действительно хотите, чтобы передать массив, а затем передать его по ссылке (или const ссылке, если вы не собираетесь изменить его) с помощью шаблона, как

template<std::size_t N> 
void listElements(/*const*/ char (&arr)[N]) 
{ 
    // sizeof(arr) will be equal to N 
    // rest of the function body here 
} 

Если вы передадите его по значению, то он распадается на указатель, то есть void listElements(char arr[]) - это то же самое, что и void listElements(charr arr[1024]) - это то же самое, что и void listElements(char* arr).

PS: обратите внимание, что если вы передадите массив по ссылке, как указано выше, то ваша функция больше не будет работать с указателями, так как в этом случае компилятор различает указатели и массивы. То есть listElements(p) не компилируется для char* p;. Если вы хотите использовать его с указателями (что может быть удобно), вы должны указать размер вручную в качестве дополнительного параметра функции или использовать какое-либо соглашение для разделителя конца массива, например строки с нулевым завершением in C.

+0

Если он разложился на указатель, то не будет ли это 'sizeof (arr)' равным 1? В любом случае, если он передает указатель, то почему размер указателя 4? –

+1

@AlexG Нет, указатели не имеют размера 1 в целом и не имеют никакой системы, о которой я знаю, в частности. Обычно они имеют размер 4 на 32-битных машинах и 8-го размера на 64-битных машинах. –

+1

@AlexG, нет, он делает его равным размеру указателя на 'char', который обычно составляет 32 или 64 бит (т. Е. 4 или 8 байтов), в зависимости от ОС. Указатель - это особый тип переменной, который хранит адрес, поэтому, если ваша ОС использует 32-разрядную адресацию, то размер указателя на 'char' (наименьшая адресуемая единица) составляет 32 бит. – vsoftco

5

char[] как аргумент функции такой же, как char* в C++. И, видимо, в вашей системе, sizeof(char*) == 4. Кроме того, sizeof(char) всегда равен 1.

Чтобы правильно передать строку стиля C, передайте ее длину как дополнительный целочисленный аргумент или, что еще лучше, используйте std::string вместо char[] и char*.

примеры кода:

void listElements(char *arr, int length){ 
    for (int j = 0; j < length; j++){ 
     cout << arr[j] << endl; 
    } 
} 

или

void listElements(const std::string& str){ 
    for (const auto& v : str) 
     std::cout << v << std::endl; 
} 
1

Вы получаете размер указателя 32-битном к нулю символ []. Эффективно, char *

3
char x[] = "Hello"; 
cout << sizeof(x) << endl; // 6 because the compiler knows x is an array of 6 characters long 

void listElements(char arr[]){ 
    cout << "Size of arr: " << sizeof(arr) << endl; // 4 arr[] is actually a pointer 

Вызов listElement() на самом деле не передает весь массив, он передает только указатель на x. Я думаю, именно поэтому вы ожидали 6.

+0

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