C программный адрес для 2d массива

Если я инициализировал 2d массив, скажем

Int a[2][3] = {
                              1, 2, 3,
                               4, 5, 6};

Является a[0] == &a[0]??

я знаю a[0] ссылается на адрес для первого элемента массива. Так и есть &a[0] еще адрес?

4 ответа

Прежде всего, тип arrayNum[0] является Int[3] и тип &arrayNum[0] является Int(*)[3] (Я не менял ОП Int к вероятному int).

Во-вторых, массивы могут распадаться на указатель на свой первый элемент, поэтому arrayNum[0] может распасться на &arrayNum[0][0] который имеет тип Int*,

Оба этих указателя, &arrayNum[0] а также &arrayNum[0][0] будет указывать на то же место, но их типы очень разные.

Есть два смысла, в которых вы можете спросить, a[0] равняется &a[0]:

Делать a[0] а также &a[0] указать на то же место?

а также:

Есть ли a[0] == &a[0] оценивать как истинное?

Из вашего вопроса не ясно, что вы имеете в виду. Ваш текст спрашивает "Есть a[0] == &a[0]? "Поскольку" == "не в формате кода, неясно, намеревались ли вы его исключить.

Ответ на первый вопрос - да (учитывая, что a[0] автоматически преобразуется в адрес), и ответ на второй вопрос не обязательно.

Как и другие ответы и комментарии, a[0] а также &a[0] это разные вещи. a это массив из двух массивов из трех int, Так a[0] это массив из трех intи в большинстве выражений он автоматически преобразуется в указатель на свой первый элемент. Таким образом, результатом является указатель на intэффективно &a[0][0], По сравнению, &a[0] это адрес массива из трех int,

Итак, эти выражения указывают на два разных объекта, но два объекта начинаются в одном и том же месте, поэтому указатели указывают на одно и то же "место". Мы можем видеть это в:

(char *) a[0] == (char *) &a[0]  // Evaluates to true.

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

Тем не менее, когда вы оцениваете a[0] == &a[0], существует проблема. Чтобы соответствовать стандарту C, сравнение указателей должно сравнивать указатели с совместимыми типами. Но int и массив из трех int не совместимые типы. Таким образом, это сравнение не совсем соответствует C, хотя некоторые компиляторы могут разрешить это, вероятно, с предупреждением. Вместо этого мы можем оценить:

a[0] == (int *) &a[0]  // Value is not specified.

Путем преобразования указателя справа в указатель на int, мы делаем левую и правую стороны одинакового типа, и мы можем сравнить их. Однако результат сравнения не определен. Это связано с тем, что, хотя стандарт C позволяет нам преобразовывать указатель на один тип в указатель на другой тип, он, как правило, не гарантирует, каково значение, полученное в результате преобразования, за исключением того, что при преобразовании его обратно в Исходный тип, тогда он будет сравниваться равным исходному указателю. (Преобразование в указатель на символьный тип является специальным; для них компилятор гарантирует, что результат указывает на первый байт объекта.)

Итак, поскольку мы не знаем, какова стоимость (int *) &a[0] есть, мы не знаем, сравнивать ли это a[0] вернет истину или ложь.

Это может показаться странным; если один адрес указывает на то же место, что и другой адрес, почему они не будут сравниваться? На некоторых компьютерах существует несколько способов обращения к одному и тому же месту в памяти. На самом деле адреса могут быть сформированы из комбинаций частей, таких как базовые адреса плюс смещения. Например, адрес (1000, 230), представляющий 1230, указывает на то же место, что и (1200, 30), также представляющий 1230. Но ясно (1000, 230) не совпадает с (1200, 30).

Когда вы сравниваете два указателя с одним и тем же типом, компилятор автоматически корректирует представления адресов любым способом, необходимым для сравнения. Но когда вы преобразуете указатель на один тип в указатель на другой (не символьный) тип, изменение типов может помешать компилятору иметь информацию, необходимую для правильной настройки. Таким образом, стандарт C не говорит нам, что происходит в этом случае.

Я не уверен, что вы хотели объединить, используя == в вашем вопросе, но позвольте мне сказать вам это, они не одинаковы.

  • Тип данных: проверьте тип данных.

    • a[0] это первый элемент массива типа int [3],
    • &a[0] указатель на первый элемент массива типа int [3]Итак, это по сути int (*) [3],
  • Использование: теперь, в зависимости от использования, в некоторых случаях, Note, "тип массива", распадается на указатель на его первый элемент. Учитывая этот случай, a[0] а также &a[0], оба эквивалентны письму &(a[0][0]), поэтому значение указателя будет таким же.

Для лучшего понимания разницы используйте оба a[0] а также &a[0] в качестве аргумента йо sizeof оператор (где затухание не происходит) и распечатать значение с помощью %zu спецификатор конверсии.

Как правило, они будут печатать

  • 12, который (sizeof (int) * 3) а также
  • 8, который sizeof (int (*) [3])

    на платформе, где размер int является 4 и размер указателя 8,


[Заметка]:

квотирование C11Глава §6.3.2.1

За исключением случаев, когда это операнд оператора size of, _Alignof оператор, или унарный& оператор или строковый литерал, используемый для инициализации массива, выражение с типом '' массив типа '' преобразуется в выражение с типом '' указатель на тип '', которое указывает на начальный элемент объекта массива и это не lvalue. [....]

Нет, они не одинаковы.

a[0] является элементом типа int[3], в то время как &a[0] указатель (типа int*[3]) на a[0],

Но оба они указывают на один и тот же адрес (первый элемент a[0]), но не совпадают.

Другие вопросы по тегам