0

这是我长期以来一直不清楚(就范围而言)的一个特定场景。

考虑代码

#include <stdio.h>


typedef struct _t_t{
    int x;
    int y;
} t_t;

typedef struct _s_t{
    int a;
    int b;
    t_t t;
}s_t;

void test(s_t & s){
    t_t x = {502, 100};
    s.t = x;
}


int main(){
    s_t s; 
    test(s);

    printf("value is %d, %d\n", s.t.x, s.t.y);
    return 0;
}

输出是

value is 502, 100

让我有点困惑的是以下内容。宣言

t_t x

在函数测试的范围内声明。所以从我读过的关于 C 编程的内容来看,它应该是超出这个范围的垃圾。然而它返回一个正确的结果。是不是因为st = x;线上的“=” 将 x 的值复制到 st?

编辑 - -

经过一些实验

#include <stdio.h>


typedef struct _t_t{
    int x;
    int y;
} t_t;

typedef struct _s_t{
    int a;
    int b;
    t_t t;
}s_t;

void test(s_t & s){
    t_t x = {502, 100};
    t_t * pt = &(s.t);
    pt = &x;
}


int main(){
    s_t s; 
    test(s);

    printf("value is %d, %d\n", s.t.x, s.t.y);
    return 0;
}

实际输出

value is 134513915, 7446516

正如预期的那样。

4

5 回答 5

7

是不是因为st = x;线上的“=” 将 x 的值复制到 st?

是的。

顺便说一句,这是 C++。您已将本地的“s”作为对函数的引用传递给 main,该函数对其进行了修改。因为它是一个引用,而不是一个副本,它会影响调用者的“s”。

于 2009-09-16T22:13:42.330 回答
6
   t_t x = {502, 100};
   s.t = x;

在您的第一个测试中,您指示编译器将值复制x到 into s.t- 这按预期工作。局部变量x超出范围,但从未在函数外部引用 - 它最初包含的数据被复制到的局部变量的t成员中。如果你改为写,它实际上是相同的:main()s

t_t x = {502, 100};
s.t.x = x.x;
s.t.y = x.y;

在您的第二个 test中,您将一个指针分配给另一个指针,这两个指针都被声明为局部变量。这没有任何用处 - in 的值s.t仍未初始化。我已经注释了代码以帮助您遵循它:

t_t x = {502, 100}; // local variable x initialized with 502, 100
t_t * pt = &(s.t); // local variable pt initialized with ADDRESS OF s.t
pt = &x; // local variable pt re-assigned to hold address of local variable x

// local variables go out of scope, output parameter s remains unmodified
于 2009-09-16T22:16:20.393 回答
1

阅读本文:默认复制构造函数和赋值运算符

通过不提供赋值运算符,结构 _s_t 将在分配时对其所有成员进行浅拷贝。因为您按值将所有内容存储在 _t_t 中,所以所有数据都按值复制。

您描述的问题是当 _t_t 持有指向数据的指针时。

在这种情况下:

typedef struct _s_t{
        int a;
        int b;
        t_t* t;
}s_t;

void test(s_t & s){
        t_t x = {502, 100};
        s.t = &x;
}

这会导致问题,因为 t_t 将在 test() 结束时被破坏,此时该指针将无效。

ETA:因为您在问题中添加了更多内容...

void test(s_t & s){
     t_t x = {502, 100};
     t_t * pt = &(s.t);
     pt = &x;
}

您在这里创建了一个不同的问题。那里发生的事情是您创建了一个指向 st 地址的指针,这很好。但是,您随后将该指针重新分配为指向 x (此分配对 st 没有任何作用,您只是在更改指针 pt 指向的内容)输出“如预期”的原因是因为您只是在读取未初始化的状态结构。

于 2009-09-16T22:18:42.747 回答
0

你是对的,线

s.t = x;

将复制这些值。

于 2009-09-16T22:13:53.457 回答
0

赋值将值从一个变量复制到另一个变量。所以虽然原来的本地 x 已经消失了,但你在 s 中有一个副本。

当您刚刚分配一个指向 x 的指针时,情况会完全不同:

typedef struct _s_t{
        int a;
        int b;
        t_t* t;
}s_t;

void test(s_t & s){
        t_t x = {502, 100};
        s.t = &x;
}

那么你会遇到一个问题:你只有 x 的地址,但 x 已经消失了。所以你有效地引用了一个无效的内存位置。该程序的行为将是未定义的。

于 2009-09-16T23:42:19.270 回答