LINUX.ORG.RU

Указатели на структуры

 


0

1

Как писал выше, начал хелловорлдить. Есть такой код:


#define MAX 10
#define WBD '*'
#define DELAY 200

struct pointworm {
		       
		       int x;
		       int y;      
    } worm[MAX]=
		
		{5,5,
			5,4,
		 4,4,
		 3,4,
		 2,4,
		 2,3,
		 }, newhead;


void movesnake( struct pointworm pworm[],struct pointworm pnewhead, int lenght)
		{
		lenght--;
	 while(lenght>0)
	 {	pworm[lenght]=pworm[lenght-1];
	 	lenght--;
	 	}
	pworm[0]=pnewhead;
	};

int main (void){
newhead=worm[0];	
int i=0,N=6;
newhead.x++;
movesnake(worm, newhead, N);
while(worm[i].x != 0 && worm[i].y != 0) {
printf("%d, %d\n",worm[i].x, worm[i].y);
i++;};
return 0;
}t
Да, программа работает, но у меня возникли вопросы. Я определил функцию с аргументами
void movesnake( struct pointworm pworm[],struct pointworm pnewhead, int lenght)
, а в программе вызвал ее
 movesnake(worm, newhead, N); 
Я передал ведь туда просто значения полей структур, и, как мне кажется, аргументы не должны изменитбся(но они поменялись, что и требовалось) или адреса? Ведь при передаче адреса, надо было передавать так movesnake(&worm, &newhead, N);, а в самой функции определять аргументы как указатели на структуры. В чем я ошибаюсь?

★★★★★

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

В случае с pworm ты по сути передаешь адрес (что полностью аналогично определению параметра pworm как struct pointworm *pworm), в случае с pnewhead ты передаешь структуру по значению, т. е. структура копируется и изменить ты её не сможешь.

В чем я ошибаюсь?

Массив в C при передаче его в функцию — это уже адрес его первого элемента. А &worm — это уже указатель на указатель, т. е. struct pointworm **.

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)

за разметку извините - пишу в android c compiler на смартфоне, компьютера рядом нет. Может кто перепосьит код? Спасибо.

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

В общем, в данном твоём случае ты всё делаешь правильно.

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

спасибо, разобрался.
[code] #define MAX 10
#define WBD '*'
#define DELAY 200
//*******************
struct pointworm {

int x;
int y;
} worm[MAX]=

{5,5,
5,4,
4,4,
3,4,
2,4,
2,3,
}, newhead;


void movesnake( struct pointworm pworm[],struct pointworm *pnewhead, int lenght)
{
lenght--;
while(lenght>0)
{ pworm[lenght]=pworm[lenght-1];
lenght--;
}
pworm[0]=*pnewhead;
*pnewhead=pworm[0];
};

int main (void){
newhead=worm[0];
int i=0,N=6;
newhead.x++;
movesnake(worm, &newhead, N);
while(worm.x != 0 && worm.y != 0) {
printf(«%d, %d\n»,worm.x, worm.y);
i++;};
printf(«newhead=%d %d»,newhead.x,newhead.y);
return 0;
}
[/code]
В ф-ю передаю адрес первого элемента pworm, указатель на newhead и длину N.

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

Поставь уже себе нормальную IDE с мышевозным трассировщиком и сам, своими глазами, увидишь, что у тебя куда передается и что где изменяется в процессе выполнения. А не будешь плодить темы в духе «я тут чота написал, объясните, как оно работает».

thesis ★★★★★
()

Хоть бы код отформатировал, я не знаю. Читать же невозможно.

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

А &worm — это уже указатель на указатель, т. е. struct pointworm **.

Неправильно. Откуда тут возмется лишний указатель? &worm — это указатель на массив из 10 struct pointworm.

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

Неправильно. Откуда тут возмется лишний указатель? &worm — это указатель на массив из 10 struct pointworm.

А ну марш читать Кернигана и Ритчи. worm - это уже указатель на массив, а &worm - соответсвенно адрес переменной, в которой хранится указатель worm.

hippi90 ★★★★★
()

У тебя что-то с форматированием кода - оно наркоманское.

DELIRIUM ☆☆☆☆☆
()
void movesnake( struct pointworm pworm[],struct pointworm pnewhead, int lenght)

Если пишешь на плюсах, перепиши вот так:

void movesnake( struct pointworm pworm[],struct pointworm &pnewhead, int lenght)

Ничего больше менять не придётся, а зато по канонам.

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

Я сейчас без компьютера - пишу с телефона в c compiler online. ИЗВИНИТЕ еще раз за форматирование.

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

Я сейчас без компьютера - пишу с телефона в c compiler online. ИЗВИНИТЕ еще раз за форматирование.

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

Я сейчас без компьютера - пишу с телефона в c compiler online. ИЗВИНИТЕ еще раз за форматирование.

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

Я сейчас без компьютера - пишу с телефона в c compiler online. ИЗВИНИТЕ еще раз за форматирование.

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

А ну марш читать Кернигана и Ритчи. worm - это уже указатель на массив, а &worm - соответсвенно адрес переменной, в которой хранится указатель worm.

Ты чего курил? В исходной программе worm — это массив.

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

Ну ё-моё, ну откройте уже K&R:

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

hippi90 ★★★★★
()

О Боже... Жалко я свою змейку в 30 строк без структур и на одномерных массивах проспал, а то показал бы.

В самом деле, нафига для змейки использовать структуры? Она же простая писец, зачем все усложнять?

Даже для обучения можно пример лучше найти.

Deleted
()

ну ты пиши так:

struct foo1
{
  int x;
  int y;
};

typdef struct foo1 foo;

foo x;// структура
foo a[17];// массив из 17и структур

ну а передаёшь ты значение в функцию. Кроме случая массива. Если ты передал массив int, то массив преобразуется в указатель на int, указывающий на эл-т №0. Это вообще говоря несколько другое.

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

Феноменально. Следуя вашей логике, sizeof(worm) должен вернуть размер указателя, не так ли?

это такая логика у K&R. До передачи — нет, после передачи в функцию — таки да. Размер самого массива безвозвратно теряется при передачи в функцию. Либо отдельно передавай, либо означай его нулём(как в строках).

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

K&R можно использовать для ознакомления с Си, а вообще-то надо читать стандарт.

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

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

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

В случае с sizeof() - это исключение, описанное в стандарте, и зависящее от контекста. В остальном, имя массива интерпретируется, как указатель на первый элемент.

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

В случае с sizeof() - это исключение, описанное в стандарте, и зависящее от контекста.

Верно.

В остальном, имя массива интерпретируется, как указатель на первый элемент.

Неверно. Подсказка: есть еще исключения. Взятие адреса массива — одно из них.

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

Так это же превосходно: ты передал в функцию 1 аргумент, и точно знаешь, что в регистры будет записан именно этот, единственный, аргумент, а не тонны шлака. А для передачи массива вместе с размером можно завести структуру — массив + размер, ссылочку на нее и передавать.

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

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

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

В случае с sizeof() - это исключение, описанное в стандарте, и зависящее от контекста. В остальном, имя массива интерпретируется, как указатель на первый элемент.

не совсем. Ну например указатель ты можешь сдвинуть куда хочешь, а вот массив — не можешь. Он ещё и const, о чём K&R AFAIK не писали. ЕМНИП ещё что-то есть. И да, sizeof зависит не от контекста, а исключительно от того, чем ты его кормишь. Массив — это не указатель. Хотя обычно ведёт себя как указатель, и часто в него преобразуется без вопросов.

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

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

ну да. Эта фича так и задумана, но ИМХО не доделана. А доделывать её уже нельзя, ибо рушится совместимость. Вот и получается, что при передаче в функцию сущность «массив» сама оборачивается сущностью «указатель».

можно завести структуру — массив + размер

и компилятор будет вынужден повсюду и везде таскать две переменные «размер». Можно сделать структуру «указатель+размер», но тогда нужно надеяться, что оптимизатор сообразит, что это одна неделимая сущность, а не две разные хреновины. И да, передавать указатель на структуру с указателем и размером не нужно. Лучше всю структуру целиком, это быстрее.

Ну и наконец: кто кричал про «костылищща»? Ты и кричал. А теперь сам предлагаешь костылить свои NIH массивы...

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

аргумент - указатель на нулевой элемент структуры.
[code] void movesnake( struct pointworm *pworm,struct pointworm *pnewhead, int lenght)
{
lenght--;
while(lenght>0)
{ pworm[lenght]=pworm[lenght-1];
lenght--;
}
*pworm=*pnewhead;
*pnewhead=*pworm;
}
[/code]
так будет более лаконично? А передавать буду
адрес нулевого элемента массива структур.
[code]
movesnake(&worm[0], &newhead, N);
[/code]

int13h ★★★★★
() автор топика
Ответ на: комментарий от emulek
void viewsnake(struct pointworm *rrr){
int i=0;
while ((*rrr).x!=0 && (*rrr).x!=0){
printf("worm[%d][%d]=%d,%d\n",i,rrr, (*rrr).x,(*rrr).y);
		rrr++;
		i++;
}
}

Выводим адресс i-го элемента массива структр, его значения. Я этим правильно , скажем так, показываю элемент и его адрес?

int13h ★★★★★
() автор топика
Ответ на: комментарий от emulek
void viewsnake(struct pointworm *rrr){
int i=0;
while ((*rrr).x!=0 && (*rrr).x!=0){
printf("worm[%d][%d]=%d,%d\n",i,rrr, (*rrr).x,(*rrr).y);
		rrr++;
		i++;
}
}

Выводим адресс i-го элемента массива структр, его значения. Я этим правильно , скажем так, показываю элемент и его адрес?

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

так будет более лаконично?

так будет ничетаемо.

 void movesnake( struct pointworm *pworm,struct pointworm *pnewhead, int lenght)
{
  lenght--;
  while(lenght>0)
  { 
    pworm[lenght]=pworm[lenght-1];
    lenght--;
  }
  *pworm=*pnewhead;
  *pnewhead=*pworm;
}

так вроде ничего, норм. У меня только два замечания:

1. for(;;) куда читаемее ИМХО

2. не очень очевидно, зачем ты _меняешь_ pworm[0], ведь старое его значение никуда не делось, а лежит в pworm[1] в любом случае. Ну разве что len==1, но этот особый случай я-бы отдельно оформил вне функции или внутри неё. А то какая-то непонятка, не сразу я понял что это за хрень.

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

Выводим адресс i-го элемента массива структр, его значения. Я этим правильно , скажем так, показываю элемент и его адрес?

1. ели rrr это массив, то почему ты пишешь не rrr[0].x?

2. правильно printf("%p", rrr);

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

Мы начали вот с этой фразы:

&worm — это указатель на массив из 10 struct pointworm.

Таки, &worm - это указатель на переменную, в которой хранится адрес массива.

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

Таки, &worm - это указатель на переменную, в которой хранится адрес массива.

Опять 25! Допустим, твое предположение верно. Ответь тогда на такой вопрос: где выделена память под эту мифическую переменную с адресом массива? Куда вот этот код запишет 0x12345678?

struct pointworm worm[MAX];
struct pointworm **pp = &worm;
*pp = (struct pointworm *)0x12345678;
Deleted
()
Ответ на: комментарий от andreyu

Ну осильте уже K&R.

Блин, еще один советчик, нифига не разбирающийся в вопросе, подтянулся. Просто тред-детектор какой-то.

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

Это Вы чего-то выдумываете. Оператор & не выдаёт указатель на переменную, в которой хранится что-то там. Он выдаёт адрес своего операнда. В случае массива он выдаст адрес массива. Сообщу также, что массив как lvalue совпадает со своим адресом, так что выражение (worm == &worm), где worm - массив, - всегда истинно.

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

Сообщу также, что массив как lvalue совпадает со своим адресом, так что выражение (worm == &worm), где worm - массив, - всегда истинно.

Верно, только типы worm и &worm разные, о чем компилятор выдаст соответствующее предупреждение.

Deleted
()

Это не код - это говно, кто вас учит? Причем похоже те бомжи, что тебе отвечали - так же писать не умеют.

Если ты учишься - сделай это красиво. Запили какую-нибудь либу, чтоб было поцаночке - это делается 10минут. Что-то типа этого: http://pastebin.com/y48cy2X1

Когда начнёшь писать по пацаночке - всякие идиотские вопросы «как юзать указатели» - уйдут. И да, в 99% случаев юзаются тайпдефы, а не «struct stname name».

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

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

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

может дадите пример хорошого кода на С в виде маленького простого проекта, выдержанного в небыдлокодерской стилистике?

int13h ★★★★★
() автор топика
Последнее исправление: int13h (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.