Чи погано посилатися на елементи масиву доступу через арифметику вказівника замість оператора []?


12

Я щойно почав вчитися програмувати на C, і щоб покращити своє розуміння покажчиків та масивів, я намагався посилатися на елементи масиву, не створюючи взагалі жодного покажчика:

for(k1 = 0; k1 < ROW; k1++){
    for(k2 = 0; k2 < COLUMN; k2++){

        array[k1][k2] = k1*COLUMN + k2 + 1;

        printf("[%d][%d] = %d\n", k1, k2, *(array[k1] + k2));

    }
}

Весь код складається і працює бездоганно.

Я думаю, що створити вказівник для кожного масиву у великому вихідному коді здається дуже неефективним.

Отже, замість того, щоб адреса масиву зберігалася та була отримана за допомогою вказівника, чи погана практика програмування безпосередньо використовувати адресу масиву, як показано вище?


Використання printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));дозволить уникнути арифміки вказівника і його легше зрозуміти.
Каспер ван ден Берг

1
Ха-ха, ти мене зрозумів. Я зробив це лише як експеримент, щоб краще зрозуміти, як працюють покажчики та масиви.
Ніко Гамбт

Арифметика вказівника насправді на 30% швидша, ніж використання індексів масиву.
Енді

Відповіді:


16

Це "погано" лише в тій мірі, в якій він менш читабельний. a[x]це те саме, що *(a+x), тому різниці в ефективності чи поведінці немає (насправді, x[a]також буде працювати). Просто a[x]це, як правило, набагато інтуїтивніше для нас людей.

Але це не означає, що читабельність - це не велика справа. Щоб побачити, наскільки великий, подумайте, як би ви «прочитали» ці два вирази, якби бачили їх у коді:

  • *(a+x)= "На те, на що вказується сума вказівника aта цілого числа x"
  • a[x]= "Таблиця xмасиву a"

Аналогічно, коли вам потрібно звернутися до адреси елемента масиву:

  • (a+x)= "Сума вказівника aта цілого числа x"
  • &a[x]= "Адреса xтретього члена масиву a"

Здебільшого []версії просто простіше зрозуміти, коли ви дивитеся на нетривіальний код, що працює на декількох різних масивах (особливо масивах масивів). Ось чому []оператор існує в першу чергу.

PS Виконувати такі речі суворо як навчальні вправи - це дуже гарна ідея. Важливо розуміти, що масиви насправді є лише покажчиками та зрушеннями.


Це. Дякую. Я щойно зрозумів у глибині душі, що я дійсно хочу знати - це чи ні, коли потрібно посилатися на адресу будь-якого елемента масиву, а потім посилатися на адресу іншого елемента, а потім іншого, це все-таки погано НЕ використовувати вказівник, а замість цього використовувати масив безпосередньо так, як я це зробив? Це моє питання було дуже важко визначити, тому я не вводив його в ОП. У будь-якому випадку, оскільки я цього не запитував, ваша відповідь задовільна.
Ніко Гамбт

1
@NikoGambt Ви завжди можете задати інше запитання =)
Ixrec

1
Що ти маєш на увазі лише в міру ...? Вся суть мов програмування полягає в тому, щоб людині було легше читати код. Якби нас це не хвилювало, тоді ми всі писали б коди в шістнадцятковій формі.
Соломон повільно

2
Масиви - це не покажчики, а просто згасання покажчиків неявно.
CodesInChaos

4

Так, це погана практика, але не з причин неефективності.

Оператор масиву використовує арифметичний покажчик під кришкою, тому вони однаково ефективні.

Проблема арифметричної вказівника полягає в тому, що вона дуже схильна до помилок і важче її читати.

Правило великого пальця: Не використовуйте арифметичні покажчики, якщо не потрібно.


1
Оскільки він так чи інакше використовує арифметику вказівника, чи це не означає, що вказівники також настільки ж схильні до помилок і важко читати?
Ніко Гамбт

1
@NikoGambt компілятори досить добре роблять арифмічні вказівники під кришкою і рідко будуть робити «помилки»; саме програмісти помиляться з неприємними помилками, як наслідок.
Каспер ван ден Берг

@KaspervandenBerg Так, я згоден. Однак мене цікавлять помилки, допущені програмістами, і я просто не зовсім впевнений, чи погана практика програмування робити те, що я робив там вище, у випадках, коли потрібно вказати адресу масиву , якщо такі випадки існують.
Ніко Гамбт

1
@NikoGambt Написання чогось менш читабельного для цілей виконання майже завжди є поганою практикою, але писати щось менш читабельне без жодних вигод - це однозначно погана практика.
Ніл

@Neil Мій маленький експеримент не є безглуздим. Роблячи це, я дізнався, що компілятор, схоже, робить масив покажчиків для позначення багатовимірного масиву. Однак, оскільки ви сказали, що читабельність важливіша за ефективність, я думаю, це все ще погана практика програмування.
Ніко Гамбт

0

Охолоджуючи своє навчання, ви щойно відкрили один із маленьких твістерів язика. Ви робите не арифметику вказівника на масиві, а масив покажчиків. Виконання арифметики вказівника на масивах неможливо. Масив занепадає до вказівника, але не є типом вказівника, який він є сам. Що у вас є (див. Коментар cmaster)

int *array[]; //This is a array to pointers of type *int. 

array[k1] + k2; //This is pointer arithmetic on one pointer stored in the array  

Перенаправлення цього вказівника дає значення, яке вказує ваш щойно обчислений вказівник. Взагалі немає сенсу робити те, що ви робите. Але ви можете лінеаризувати масив, а потім крокувати в ньому, як це.

int array[y_dim*x_dim]; 
int index = x_dim*y + x; 
array[index]; //Gives you the element in x, y!

Стрий її - x_dim. Сподіваюся, моя відповідь з’ясовується!


З ОП незрозуміло, чи він використовує int* array[ROW];ан int array[ROW][COLUMN];, чи ан int (*array)[COLUMN];. Будь-яке з цих трьох визначень може використовуватися з кодом в ОП.
cmaster - відновити моніку

так, я знаю про це, моя відповідь трохи незграбна з цього приводу. Я виправляю це, дякую!
fhtuft
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.