Joh*_*udy 13 c struct pointers reference
这听起来像是一个愚蠢的问题,但我还在学习C,所以请耐心等待.:)
我正在研究K&R(结构)的第6章,到目前为止,这本书已经取得了巨大的成功.我决定使用相当多的结构,因此在本章的早期就使用了point和rect示例做了很多工作.我想尝试的其中一件事是canonrect通过指针改变功能(第2版,第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?(IE,如果我canonRect(*r);进去了main().)我怀疑我已经知道了#1的答案,但#2让我感到困惑 - 我认为传递指针是合法的.
无论如何......请原谅C newb.
Bri*_*ndy 18
我想你想要做的是:
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; 
}
在上面的代码中,您设置*r,其类型为rect,类型为rect.
Re 1:如果你想改变r指向的东西,你需要使用指向指针的指针.如果这真的是你想要的(见上文,它不是你想要的那样)那么你必须确保将它指向堆上的东西.如果你将它指向不是用'new'或malloc创建的东西,那么它将超出范围,你将指向不再用于该变量的内存.
为什么你的代码不适用于r =&temp?
因为r是rect*类型.这意味着r是一个变量,它保存一个内存包含一个rect的内存地址.如果你改变r指向的东西,那很好,但这不会改变传入的变量.
Re 2:*未在类型声明中使用时是解引用一元运算符.这意味着它将查找指针地址内的内容.所以通过传递*r你根本就没有传递指针.因为r不是指针,所以语法无效.
听起来您好像在混淆“取消引用”运算符(*)和“地址”运算符(&)。
当您编写时&r,它将获取r的地址并返回一个指向r的指针(指针只是变量的内存地址)。因此,您实际上是在将指针传递给函数。
在编写时*r,您试图取消对r的引用。如果r是一个指针,它将返回r指向的值。但是r不是指针,而是rect,因此您会得到一个错误。
为了使事情更加混乱,*在声明指针变量时还使用了字符。在此函数声明中:
void canonRect(struct rect *r) {
r声明为的指针struct rect。这*与这样使用完全不同:
canonRect(*r); 
在两种情况下,*字符都表示完全不同的东西。