LINUX.ORG.RU

Указатель на указатель массива указателей

 


2

1

Правильно говорят, что указатели в С и наследниках, для начинающего, выглядят чем-то средним между регекспами и матаном. И если с регекспами я начинаю практически сталкиваться и чуток понимать, то до ваших интегралов мне профтехобразование не позволяет доползти. Так вот, этот ваш Си - на самом деле довольно несложен, так как логичен, но с указателями у меня вышел небольшой разлад. Ну не понимаю как оно внутри работает, как к памяти обращается. Подскажите, пожалуйста, кому не лень...

// Из K&R:
int х = 1, у = 2;
int *ip;    /* ip - указатель на int */
ip = &x;    /* теперь ip указывает на x */
y = *ip;    /* y теперь равен 1 */
*ip = 0;    /* x теперь равен 0 */
В чем смысл указателей, если судя по примеру я могу сделать и y = x с тем же успехом, а дополнительные *ip как посредники лишь уменьшат читаемость?

UPDATE: Самое главное еще забыл добавить - зачем к этой кашке еще и «**»?

UPDATE++: посылаю комментаторам доброе слово, без них вопрос затянулся бы

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 3)

Почитай немного дальше и станет ясно зачем они. Часто проще записать, запомнить возникшие вопросы и вернуться к ним позже.

anonymous
()

K&R хорошо же объясняют...

Указатель - переменная, значением которой является адрес другой переменной. Смысл - в косвенном доступе.

anonymous
()
Ответ на: комментарий от anonymous

Теоретически, я понимаю принцип их работы, однако пока не нахожу плюсов в таком подходе, указал же - переменные можно ведь и напрямую менять, зачем посредники?

minakov ★★★★★
() автор топика
Последнее исправление: minakov (всего исправлений: 1)
Ответ на: комментарий от anonymous

на болгарке и сварочном аппарате, в хедере треда даже это указано, мил человек

minakov ★★★★★
() автор топика

Указатель на указатель массива указателей

И где это в коде?

// сам как-то вытворял трюки с массивом указателей, чтобы медиану быстрее считать.

Eddy_Em ☆☆☆☆☆
()

Как уже сказали косвенный доступ, можно писать не только функции кторые будут модифицировать данные по переданному указателю, но и хитрить. Например, разыменовать 4 uchar как ulong.

nand
()
Ответ на: комментарий от minakov

Это — простейший пример. А ты попробуй две огроменных структуры так же местами поменять.

Eddy_Em ☆☆☆☆☆
()

Самый простой пример применения: возможность написания void swap(int* x,int* y), которая меняет местами значения переменных.

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

А ** - это массив указателей, он же указатель на первый указатель из массива указателей.

AITap ★★★★★
()
Ответ на: комментарий от nand

Например, разыменовать 4 uchar как ulong

Ага. Я сам так хотел делать намедни, пока не «открыл для себя» стандартные макросы вроде htobe64.

Eddy_Em ☆☆☆☆☆
()

Читай K&R дальше, со временем прийдёт понимание. Поинтеры — это самая главная плюшка C. Если ты их не осилишь — то ты и не будешь знать C.

beastie ★★★★★
()
Ответ на: комментарий от Eddy_Em

Дальше по треду вангую этот вопрос, а точнее ответ на этот вопрос, если мне разжуют про надобность... Пока не вижу логики в указателях и адресах

minakov ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Я на МК так хитрил. Про htobe64 не знал, а один раз разыменовать оказалось лаконичнее сдвигов.

nand
()

K&R настолько упростили, что смысл потерялся.
Вот надо тебе установить несколько переменных

int a=0;
int b=0;
int c=0;
int d=0;

есть функция, c параметрами указателями

int fill_abcd(int * a,int * b,int * b,int * c)
{
*a=1;
*b=2;
*c=3;
*d=4;
return 1;//ok
}

переменные заполняются вызовом

fill_abcd(&a,&b,&c,&d);

после вызова a=1,b=2,c=3,d=4;

ilovewindows ★★★★★
()
Ответ на: комментарий от minakov

А функции ты уже освоил? Напиша-ка функцию, которая изменяет переданные ей данные.

Для динамических структур данных. Ты программист вообще? Связный список знаешь что такое?

В общем, читай дальше.

anonymous
()
Ответ на: комментарий от AITap

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

Интересное, но почему этим должен заниматься человек? Уж такой примитивный случай для совремеменных компиляторов как два пальца об асфальт.

lazyklimm ★★★★★
()

изучи какой-нибудь ассемблер сначала, тогда понятнее будет

Harald ★★★★★
()

Читай спокойно дальше.
Составные типы данных, динамические структуры данных (деревья, стеки, очереди) передача их в качестве параметров, передача функций или массивов в качестве параметров. ЗЫ. Собственно, врубись как вообще происходит передача данных в функцию. И как передать функции видюшку весом в гигабайт.

thesis ★★★★★
()
Последнее исправление: thesis (всего исправлений: 1)
typedef struct node {
    void *data; // указываем на данные
    struct node *next; // указываем на следующий элемент
} node_t;

Как использовать, сам догадаешься?

Хотя, ты ведь еще и про динамическую память не знаешь... Программировал раньше?

anonymous
()
Ответ на: комментарий от ilovewindows

переменные заполняются вызовом

И здравствуй, путаница с возвратом (тут вернём результатом, тут по указателю, а тут вместе)

lazyklimm ★★★★★
()
Ответ на: комментарий от lazyklimm

почему этим должен заниматься человек?

В учебных целях?
Ну, или если код от этого получится более красивым, вроде while (--argc && ++argv) { ... };

Сам не использую, да и на C почти не пишу.

AITap ★★★★★
()
Ответ на: комментарий от lazyklimm

Это более общая концепция. См. С++ итераторы(указатели подходят под критерий итераторов произвольного доступа).

anonymous
()
Ты когда-нибудь играл в игру, когда ты находишь записку, а в ней написано, где лежит следующая, и пройдя по цепочке записок ты находишь приз?

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

char* a; //записка, которая приведет к призу в виде char-значения 
char** b; //записка, которая приведет к следующей записке, а вторая записка приведет к призу.
trex6 ★★★★★
()
Ответ на: комментарий от minakov

Теоретически, я понимаю принцип их работы, однако пока не нахожу плюсов в таком подходе, указал же - переменные можно ведь и напрямую менять, зачем посредники?

указатели позволяют менять переменные, не зная их адрес заранее

Harald ★★★★★
()
Ответ на: комментарий от ilovewindows

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

minakov ★★★★★
() автор топика
Ответ на: комментарий от AITap

В учебных целях?

в учебных целях как было сказано выше, лучше потыкать ассемблер

while (--argc && ++argv)

map(megafunction, argv) красивше

lazyklimm ★★★★★
()
Ответ на: комментарий от minakov

Если знаешь питон, то считай, что указатели в Си нужны для ссылочной семантики, т.е. для поведения, аналогичного питоновским переменным.

anonymous
()
Ответ на: комментарий от ilovewindows
>return 1;//ok
Не канонично. Должно 0 возвращать.
trex6 ★★★★★
()
Ответ на: комментарий от anonymous

А C и не надо брать, если не знаешь, что хочешь.

именно! Или если ничего больше не остаётся :/

lazyklimm ★★★★★
()
Ответ на: комментарий от nand
Я несколько лет подряд эту муру 30-летним дяденькам преподавал, у меня теперь есть куча всяких простых но полностью верных объяснений для сложных вещей.
trex6 ★★★★★
()
Последнее исправление: trex6 (всего исправлений: 1)
Ответ на: комментарий от minakov

если мне разжуют про надобность... Пока не вижу логики в указателях и адресах

Посмотри внимательнее на указатели на массивы строк, которые тоже представлены, как указатели. Когда въедешь в это дело, надобность сразу увидишь.

Скажем, работа с переданными в программу параметрами в **argv.

DeVliegendeHollander ★★
()
Ответ на: комментарий от trex6

Пора публикацию делать. Действительно доступно. У нас помню в институте так норм и не рассказали про указатели, к концу семестра это было какое-то запретное слово прям. Потом на ходу доучились все.

nand
()
Ответ на: комментарий от nand

Надо бы, но большинство таких объяснений ушли в неведомые глубины памяти и всплывают только при необходимости.

Может быть в следующем году удастся устроиться преподавать в какой-нибудь ВУЗ, освежить знания. После этого можно будет и о публикации подумать.

trex6 ★★★★★
()
Ответ на: комментарий от anonymous

См. С++ итераторы

кстати, тоже та ещё мерзопакость, не потому, что мерзопакость, а потому что без них никуда, даже если они и нафиг не нужны

примеры навскидку: transform(костыли с BOOST_FOREACH лучше, чем ничего, но таки костыли), find(в случае простого определения принадлежности контейнеру).

И это, блин, язык высокого уровня: «ехал итератор через итератор»

lazyklimm ★★★★★
()
Ответ на: комментарий от Eddy_Em

Семестр был всего, да и честно времени не было совсем вникать ибо был матан, физика, основы цепей. Потом, разумеется, литературу приобрели и залатали пробелы по интересам.

nand
()
Ответ на: комментарий от nand

вам

там, емнип, у меня в профиле было написано, что лучше на «ты», так что, если не затруднит...

мешает

да ничего не мешает, я не про себя

lazyklimm ★★★★★
()
Ответ на: комментарий от nand

У нас помню в институте так норм и не рассказали про указатели, к концу семестра это было какое-то запретное слово прям.

у нас тоже было хреново с этим, так что я долгое время выползал только на знании паскаля(со школы) и знакомстве с асмом(сам).

С C начал разбираться когда после длительного академа вышел и стал писать курсовик.

lazyklimm ★★★★★
()
Ответ на: комментарий от ilovewindows

напиши OUT a

я про множественные возращаемые значения, если что.

Да, и в сложные типы полноценно даже C++ не умеет, что уж говорить про C.

lazyklimm ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.