代码之家  ›  专栏  ›  技术社区  ›  ldog

C变量范围特定问题

  •  0
  • ldog  · 技术社区  · 17 年前

    这是一个我很长时间以来一直不清楚的特定场景(在范围方面)。

    考虑一下代码

    #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
    

    果不其然。

    5 回复  |  直到 17 年前
        1
  •  7
  •   Jonathan Graehl    17 年前

    是因为行s.t=x上的“=”;将x的值复制到s.t中吗?

    对。

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

        2
  •  6
  •   Test Employee 2    17 年前
       t_t x = {502, 100};
       s.t = x;
    

    在第一次测试中 ,您正在指示编译器 复制 价值 x 进入之内 s.t -这按预期工作。局部变量 X 超出范围,但从未在函数外部引用-它最初包含的数据将复制到 t 成员 main() 的局部变量 s .如果你改为写:

    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
    
        3
  •  1
  •   Salgar    17 年前

    阅读此: Default copy-constructors and assignment operators

    如果不提供赋值运算符,则结构在赋值时将对其所有成员执行浅拷贝。因为您按值存储所有数据,所以所有数据都是按值复制的。

    您所描述的问题是何时保存数据指针。

    在这种情况下:

    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()结束时被销毁,此时指针将无效。

    埃塔:因为你增加了更多的问题…

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

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

        4
  •  0
  •   rahularyansharma    17 年前

    你说得对,台词

    s.t = x;
    

    将复制值。

        5
  •  0
  •   codymanix    17 年前

    asignment将值从一个变量复制到另一个变量。所以,虽然原始的本地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不见了。因此,您实际上引用了一个无效的内存位置。那么这个程序的行为将是未定义的。

    推荐文章