2016-04-20 9 views
-1

Здесь у меня есть 2D-массив. Я хочу, чтобы указатель указывал на первую строку массива. Сначала я сделал что-то вроде этогоКакая разница между этими двумя объявлениями указателя

#include <stdio.h> 

int main() 
{ 
    int arr[2][2]={{6,2},{3,4}}; 
    int *ptr=arr; 

    printf("%d",*(ptr+0)); 
} 

Первая строка 2D-массива также представляет собой массив. Подобный тип объявления указателя для массива 1D не дает никакого предупреждения. Почему я получаю предупреждение во время компиляции.

[Предупреждение] инициализации от несовместимого типа указателя [включено по умолчанию]

Следующая не дает каких-либо предупреждений

int main() 
{ 
    int arr[2][2]={{6,2},{3,4}}; 
    int (*ptr)[2]=arr; 

    printf("%d",*(ptr+0)); 
} 
+2

Это то же самое, что разница между домом и кухней или между человеком и пальцем. –

+0

Вот предупреждение для строки 'printf' во втором фрагменте, если вы его пропустили: **" check.c: 8: 17: warning: format указывает тип 'int', но аргумент имеет тип 'int *' [ -Wformat] "** – user3386109

ответ

1

arr представляет собой массив массивов целых чисел в то время как ptr - указатель на целое число. В массиве массивов вам нужно два уровня косвенности для достижения целого числа (arr[0][0]), в то время как указатель вам нужен только один (ptr[0]). Вы можете назначить массив элементов определенного типа указателю на элемент того же типа, но не в том случае, если типы различны, что здесь имеет место.

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

-2

2D-массивы содержат (как упомянуто в качестве arrurri) указатель, который указывает на массив указателей, и каждый из них указывает на фактические элементы. Таким образом, arr является указателем на указатели, и каждое его индексированное значение (arr [i]) является указателем на строку.

Итак, что вам нужно сделать, это ptr = arr [0]; вместо.

+1

Массивы * не содержат никаких указателей на любые элементы; выражения массива * преобразуются * в выражения указателя по мере необходимости. Если вы изучите байты 2D массива байтом, вы не найдете в нем значений указателей; вы сами найдете только элементы массива. –

+0

Моя плохая формулировка того. Я имел в виду, что каждый элемент 1-го измерения в массиве (каждый arr [i]) является указателем (указывающим на массив размера j), тогда как каждый arr [i] [j] является значением, а arr является указателем к массиву размера i (который, как уже упоминалось, имеет указатели как элементы). Разве это не так? – DGounaris

+0

Нет, это не так. Ни 'arr', ни любое' arr [i] 'не хранит значение указателя. Во время трансляции выражения * arr * и arr [i] 'по мере необходимости заменяются значениями указателей, но для любых указателей внутри объекта массива не сохраняется память. См. Пример макета в конце моего ответа. –

2

исключения случаев, когда это операнд из sizeof или одинарных & операторов, выражения типа «N -элементного массива T» будет преобразован («распад») к выражению типа «указатель на T» , а значение выражения будет адресом первого элемента массива.

В строке

int *ptr=arr; 

экспрессииarr имеет тип "2-элемент массива 2-элемента массива int" (IOW, T "2-элемент массива int"). Так как выражение arr не является операндом либо sizeof, либо унарных операторов &, оно преобразуется («распады») в выражение типа «указатель на 2-элементный массив int» или int (*)[2], а значение выражения является адресом первого элемента массива.

Вот почему вы получили предупреждение за выше линии, но не для

int (*ptr)[2]=arr; 

, так как в этом случае типы совпадают правильно.

Учитывая заявление

int arr[2][2]={{6,2},{3,4}}; 

следующие все верно:

Expression   Type   Decays To   Equivalent Value 
----------   ----   ---------   ---------------- 
     arr   int [2][2]  int (*)[2]   &arr[0][0] 
     &arr   int (*)[2][2]      &arr[0][0] 
     *arr   int [2]   int *    &arr[0][0] 
    arr[i]   int [2]   int *    &arr[i][0] 
    &arr[i]   int (*)[2]       &arr[i][0] 
    *arr[i]   int         arr[i][0] 
arr[i][j]   int         
&arr[i][j]   int *    

Так arr, &arr, arr[0], &arr[0] и &arr[0][0] все оценки одной и той же значения (адрес первый элемент массива совпадает с адресом самого массива), но типов все разные.

Очень важный момент, который я хочу получить (особенно потому, что он показан в нескольких других ответах) состоит в том, что объекты массива не хранить любые значения указателя. Если посмотреть на содержимое arr в памяти, вы увидите что-то вроде следующего:

 +---+ 
arr: | 6 | arr[0][0] 
    +---+ 
    | 2 | arr[0][1] 
    +---+ 
    | 3 | arr[1][0] 
    +---+ 
    | 4 | arr[1][1] 
    +---+ 

Нет хранения не установлен в стороне в любом месте для любых указателей. Когда ваш код скомпилирован, любые выражения, относящиеся к массивам, - , заменяют указателями на первый элемент массива.

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