0

这是一个特定的场景,我很长时间以来一直不清楚(在范围上)。C变量作用域特定问题

考虑代码

#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编程的内容来看,它应该是垃圾超出了这个范围。但它返回正确的结果。是因为线上的“=” s.t = x; 将x的值复制到s.t?

编辑---

经过一番实验

#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 

预期。

+0

有关该语言的争论点很重要。你的titla和标签说“c”,但你的代码是“C++”。 – dmckee

+0

不是C.这是C++,带有强调C的重音。 – pmg

+0

被重新标记以反映投诉 – Novelocrat

回答

7

是否因为“=”在行s.t = x;将x的值复制到s.t?

是的。

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

0

你说得对,行

s.t = x; 

将值复制过来。

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

在你的第一个测试,你告诉编译器副本x价值为s.t - 这个按预期工作。局部变量x超出范围,但从未在函数外引用 - 它最初包含的数据被复制到main()的局部变量st成员中。这将是有效的一样,如果你不是这样写道:

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

在你的第二个测试,你一个指针赋给另一个指针,这两者都声明为局部变量。这没有任何用处 - 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 
1

阅读本:Default copy-constructors and assignment operators

通过不提供赋值运算符,该结构_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将在试验(),在该点该指针将是无效的端部被破坏。

ETA:由于您添加了更多的问题......

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

你已经创建了一个不同的问题在这里。发生了什么,你已经创建了一个指向s.t地址的指针,这很好。然而,你已经重新分配了指向x的指针(这个赋值对st没有任何作用,你只是改变指针pt指向的内容) 输出结果'如预期'的原因是因为你刚刚读取了未初始化的状态的结构。

0

一个asignment将一个变量的值复制到另一个变量中。所以虽然原来的本地x不见了,但你已经有了一份副本。

当你刚分配的指针,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不见了。所以你已经有效地引用了无效的内存位置。这个程序的行为将是未定义的。