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]
), но не совпадают.