2016-04-05 5 views
0

example Простой:Почему на одной переменной мне нужно указать адрес памяти, а на массиве мне это не нужно?

double array[] = {1000.0, 2.0, 3.4, 17.0, 50.0}; 
double *p1 = array; 
printf("p1: %f\n", *(p1)); 

int x = 2; 
int* p2 = &x; 
printf("p2: %d\n", *p2); 

почему на p1 мне нужно использовать & и на массиве не нужно это в C/C++? Есть логическая причина?

+0

Поскольку массив является адресом/указателем? –

+0

Переменная нет? – markzzz

+4

@FirstStep: Нет, массив - это * не * адрес. Выражение массива неявно преобразуется в адрес его 0-го элемента в большинстве контекстов. –

ответ

1

Вы можете думать, что массив оценивает переменную типа 'address', а x - переменную типа int. x сохраняется в ячейке памяти, а & x указывает адрес этой ячейки памяти.

Адрес массива, то есть массив & будет оценивать адрес первого элемента и, следовательно, адрес самого массива.

0

Согласно книге Бьярне Страуструпа - Programming: Principles and Practice Using C++ имя массива относится ко всем elemnts массива, так, например:

char ar[10]; 
sizeof(ar) // 10 

Однако имя массива превращается в («распадается на») указатель с малейшее оправдание.

Так вот почему мы можем иметь: char* c = ar. Теперь c инициализируется &c[0] (т.е. первый элемент массива), что делает sizeof(c) 4 (в зависимости от реализации.

Что касается переменной это только один элемент.

+0

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

+0

@Slava Я добавил ссылку для ответа - надеюсь, теперь ясно – sebap123

0

Поскольку массив распадается на указатель этого декларируется тип, который указывает на первый элемент, который удерживает массив.

1

указатель массива в выражениях преобразуется (за редким исключением) на указатель на его первый элемент.

от C Standard (6.3.2.1 Lvalues, массивы , и функции)

3 исключением случаев, когда это операнд оператора SIZEOF или унарный & оператора, или является строка символов используется для инициализации массива, выражения, которое имеет типа «» массив типа «» преобразуется к выражению с типом '' указатель на тип '', который указывает на исходный элемент объекта массива и не является значением lvalue. Если объект массива имеет класс хранения регистров, поведение не определено.

И от стандарта C++ (4.2 Массива к указателю преобразования)

1 именующим или RValue типа «массив NT» или «массив неизвестного связанного Т» может быть преобразуется в prvalue типа «указатель на T». Результат является указателем на первый элемент массива.

Таким образом, эта декларация

double *p1 = array; 

эквивалентно

double *p1 = &array[0]; 
      ^^^ 

Рассмотрим эту показательной программы

$include <iostream> 

int main() 
{ 
    double array[] = { 1000.0, 2.0, 3.4, 17.0, 50.0 }; 

    std::cout << "sizeof(array) = " << sizeof(array) << std::endl; 
    std::cout << "sizeof(array + 0) = " << sizeof(array + 0) << std::endl; 
}  

Выход программы

sizeof(array) = 40 
sizeof(array + 0) = 8 

В первом выходном выражении обозначение массива используется в качестве операнда оператора sizeof. Таким образом, нет преобразования от типа double[5] до double *.

Во втором выходном выражении обозначение массива используется в выражении array + 0, которое, в свою очередь, используется в качестве операнда оператора sizeof. В этом случае происходит преобразование типа double[5] в тип double *.

Смежные вопросы