Інші відповіді правильні, але жодна з них не підкреслює думку про те, що всі троє можуть містити однакове значення , і тому вони якимось чином неповні.
Причина цього неможливо зрозуміти з інших відповідей полягає в тому, що всі ілюстрації, хоча і корисні та, безумовно, розумні за більшості обставин, не вкривають ситуацію, коли вказівник xвказує на себе.
Це досить легко побудувати, але зрозуміло трохи складніше. У програмі нижче ми побачимо, як ми можемо змусити всі три значення бути однаковими.
ПРИМІТКА . Поведінка в цій програмі не визначено, але я публікую її тут як цікаву демонстрацію того, що вказівники можуть зробити, але не повинні .
#include <stdio.h>
int main () {
int *(*x)[5];
x = (int *(*)[5]) &x;
printf("%p\n", x[0]);
printf("%p\n", x[0][0]);
printf("%p\n", x[0][0][0]);
}
Це компілюється без попереджень як у C89, так і у C99, а вихідний такий:
$ ./ptrs
0xbfd9198c
0xbfd9198c
0xbfd9198c
Цікаво, що всі три значення однакові. Але це не повинно бути сюрпризом! Спочатку давайте розбимо програму.
Ми оголосимо xяк вказівник на масив з 5 елементів, де кожен елемент має тип вказівника на int. Ця декларація виділяє 4 байти на стеку виконання (або більше залежно від вашої реалізації; на моїй машині покажчики - 4 байти), тому xце стосується фактичного місця в пам'яті. У сімействі мов C вміст - xце лише сміття, щось, що залишилося від попереднього використання локації, тому xсам по собі нікуди не вказує - звичайно, не на виділений простір.
Тож, природно, ми можемо взяти адресу змінної xі помістити її кудись, тож саме це і робимо. Але ми підемо вперед і вкладемо його в х себе. Оскільки &xмає інший тип, ніж xнам, нам потрібно зробити акторський склад, щоб ми не отримували попереджень.
Модель пам'яті виглядала б приблизно так:
0xbfd9198c
+------------+
| 0xbfd9198c |
+------------+
Отже, 4-байтовий блок пам'яті за адресою 0xbfd9198cмістить бітовий малюнок, відповідний шістнадцятковим значенням 0xbfd9198c. Досить просто.
Далі роздруковуємо три значення. Інші відповіді пояснюють, на що посилається кожен вираз, тому стосунки мають бути зрозумілими вже зараз.
Ми можемо бачити, що значення однакові, але лише в сенсі дуже низького рівня ... їх бітові структури однакові, але дані типу, пов'язані з кожним виразом, означають, що інтерпретовані значення різні. Наприклад, якщо ми роздрукували за x[0][0][0]допомогою рядка формату %d, ми отримали б величезне від’ємне число, тому «значення» на практиці різні, але бітовий малюнок той самий.
Це насправді дуже просто ... на діаграмах стрілки просто вказують на одну і ту ж адресу пам'яті, а не на різні. Однак, хоча нам вдалося витіснити очікуваний результат із невизначеної поведінки, це просто так - невизначено. Це не виробничий код, а просто демонстрація заради повноти.
У розумній ситуації ви будете використовувати mallocдля створення масиву 5 вказівних покажчиків і знову для створення ints, на які вказується цей масив. mallocзавжди повертає унікальну адресу (якщо у вас немає пам’яті; в такому випадку вона повертає NULL або 0), тому вам ніколи не доведеться турбуватися про подібні вказівники.
Сподіваємось, це повна відповідь, яку ви шукаєте. Ви не повинні сподіватися x[0], x[0][0]і x[0][0][0]бути рівними, але вони можуть бути, якщо їх змусити. Якщо щось перейшло тобі над головою, дай мені знати, щоб я міг уточнити!
x[0],x[0][0]іx[0][0][0]мають різні типи. Їх не можна порівняти. Що ви маєте на увазі під!=?