Это будет звучать как глупый вопрос, но я все еще изучаю C, поэтому, пожалуйста, несите меня.:)
Я работаю над 6-й главой K & R (structs), и до сих пор через книгу был достигнут большой успех. Я решил работать с структурами довольно сильно и поэтому много работал в начале главы с примерами и примерами. Одна из вещей, которую я хотел попробовать, заключалась в изменении функции canonrect
(2nd Edition, p 131) с помощью указателей и, следовательно, возврата void
.
У меня есть эта работа, но я столкнулся с икотой, которую я надеялся, что вы, ребята, смогли мне помочь. Я хотел canonrect
создать временный объект прямоугольника, выполнить его изменения, а затем переназначить указатель, который он передал на временный прямоугольник, тем самым упростив код.
Однако, если я это сделаю, rect не изменится. Вместо этого я обнаружил, что вручную переполняю поля rect, в которые я прошел, что работает.
Следующий код:
#include <stdio.h>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
struct point {
int x;
int y;
};
struct rect {
struct point lowerLeft;
struct point upperRight;
};
// canonicalize coordinates of rectangle
void canonRect(struct rect *r);
int main(void) {
struct point p1, p2;
struct rect r;
p1.x = 10;
p1.y = 10;
p2.x = 20;
p2.y = 40;
r.lowerLeft = p2; // note that I'm inverting my points intentionally
r.upperRight = p1;
printf("Rectangle, lower left: %d, %d; upper right: %d %d\n\n",
r.lowerLeft.x, r.lowerLeft.y, r.upperRight.x, r.upperRight.y);
// can't pass a pointer, only a reference.
// (Passing pointers results in illegal indirection compile time errors)
canonRect(&r);
printf("Rectangle, lower left: %d, %d; upper right: %d %d\n\n",
r.lowerLeft.x, r.lowerLeft.y, r.upperRight.x, r.upperRight.y);
}
void canonRect(struct rect *r) {
struct rect temp;
temp.lowerLeft.x = min(r->lowerLeft.x, r->upperRight.x);
temp.lowerLeft.y = min(r->lowerLeft.y, r->upperRight.y);
temp.upperRight.x = max(r->lowerLeft.x, r->upperRight.x);
temp.upperRight.y = max(r->lowerLeft.y, r->upperRight.y);
r = &temp; // doesn't work; my passed-in rect remains the same
// I wind up doing the following instead, to reassign all
// the members of my passed-in rect
//r->lowerLeft = temp.lowerLeft;
//r->upperRight = temp.upperRight;
}
Итак, вот вопросы:
- Почему
r = &temp;
не работает? (Я думаю, потому что я передаю ссылку вместо указателя; правильно ли я считаю, что ссылки не изменяемы, но указатели?) - Почему я могу получить незаконную ошибку времени компиляции, если попытаюсь передать указатель на
canonrect
? (IE, если у меняcanonRect(*r);
вmain()
.)
Я подозреваю, что я уже знаю ответ на # 1, но №2 меня озадачивает - я думал, что законно передавать указатели.
В любом случае... прошу простить C newb.