Это будет звучать как глупый вопрос, но я все еще изучаю C, поэтому, пожалуйста, потерпите меня. :)
Я работаю над 6-й главой K & R (структура), и до сих пор в книге были замечены большие успехи. Я решил довольно много работать со структурами, поэтому в начале главы проделал большую работу с точными и прямыми примерами. Одна из вещей, которую я хотел попробовать, - изменить работу функции canonrect
(2nd Edition, p 131) с помощью указателей и, следовательно, вернуть void
.
У меня это работает, но я столкнулся с ошибкой, я надеялся, что вы, ребята, сможете мне помочь. Я хотел canonRect
создать объект временного прямоугольника, выполнить его изменения, а затем переназначить указатель, который передается во временный прямоугольник, упрощая таким образом код.
Однако, если я это сделаю, прямоугольник не изменится. Вместо этого я обнаруживаю, что заново заполняю поля прямоугольника, в который я прошел, и это работает.
Код следует:
#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
? (То есть, если бы у меня было canonRect(*r);
в main()
.)
Я подозреваю, что уже знаю ответ на # 1, но # 2 сбивает меня с толку - я думал, что это было законно, чтобы указатели вокруг.
В любом случае ... пожалуйста, прости новичка C.