精华内容
下载资源
问答
  • 结构体对象使用malloc初始化时候有办法直接对结构体变量赋值吗?
  • 在 dotnet 运行时中,给引用对象进行赋值替换的时候...给结构体对象赋值,如果此结构体是某个类的成员字段,那么此赋值不一定是线程安全的。是否线程安全,取决于结构体的大小,取决于此结构体能否在一次原子赋值内完成

    在 dotnet 运行时中,给引用对象进行赋值替换的时候,是线程安全的。给结构体对象赋值,如果此结构体是某个类的成员字段,那么此赋值不一定是线程安全的。是否线程安全,取决于结构体的大小,取决于此结构体能否在一次原子赋值内完成

    大家都知道,某个执行逻辑如果是原子逻辑,那么此逻辑是线程安全的。原子逻辑就是一个非 A 即 B 的状态的变更,绝对不会存在处于 A 和 B 中间的状态。满足于此即可称为线程安全,因为线程不会读取到中间状态。在 dotnet 运行时里面,特别对了引用对象,也就是类对象的赋值过程进行了优化,可以让对象的赋值是原子的

    从运行时的逻辑上,可以了解到的是引用对象的赋值本质上就是将新对象的引用地址赋值,对象引用地址可以认为是指针。在单次 CPU 运算中可以一次性完成,不会存在只写入某几位而还有某几位没有写入的情况

    大概可以认为在 x86 上,单次的原子赋值长度就是 32 位。这也就是为什么 dotnet 里面的对象地址设计为 32 位的原因

    但是对于结构体来说,需要分为两个情况,定义在栈上的结构体,如某个方法的局部变量或参数是结构体,此时的结构体是存放在栈上的,而在 dotnet 里面,每个线程都有自己独立的栈,因此放在栈上的结构体在线程上是独立的,相互之间没有影响,也就是线程安全的

    如果是放在堆上面的结构体,如作为某个类对象的字段,此时的结构体将会占用此类对象的内存空间,如对以下代码的内存示意图

        class Foo
        {
            public int X; // 没有任何项目或理由可以公开字段,本文这里不规范的写法仅仅只是为了做演示而已 (Unity除外)
            public FooStruct FooStruct;
            public int Y;
        }
    
        struct FooStruct
        {
            public int A { set; get; }
            public int B { set; get; }
            public int C { set; get; }
            public int D { set; get; }
        }

    此时的 Foo 对象在内存上的布局示意图大概如下

    如上面示意图,在内存布局上,将会在类内存布局上将结构体展开,占用类的一段内存空间。也就是说本质上结构体如命名,就是多个基础类型的组合,实际上是运行的概念。也就是说在给类对象的字段是结构体进行赋值的时候,每次赋值的内容仅仅是取决于原子长度,如 x86 下使用 32 位进行赋值,相当于先给 FooStruct 的 A 进行赋值,再给 FooStruct 的 B 进行赋值等等。此时如果有某个线程在进行赋值,某个线程在进行读取 Foo 对象的 FooStruct 字段,那么也许读取的线程会读取到正在赋值到一半的 FooStruct 结构体

    如以下的测试代码

        class Program
        {
            static void Main(string[] args)
            {
                var taskList = new List<Task>();
    
                for (int i = 0; i < 100; i++)
                {
                    var n = i;
                    taskList.Add(Task.Run(() =>
                    {
                        while (Foo != null)
                        {
                            var fooStruct = new FooStruct()
                            {
                                A = n,
                                B = n,
                                C = n,
                                D = n
                            };
    
                            Foo.FooStruct = fooStruct;
    
                            fooStruct = Foo.FooStruct;
                            var value = fooStruct.A;
                            if (fooStruct.B != value)
                            {
                                throw new Exception();
                            }
    
                            if (fooStruct.C != value)
                            {
                                throw new Exception();
                            }
    
                            if (fooStruct.D != value)
                            {
                                throw new Exception();
                            }
                        }
                    }));
                }
    
                Task.WaitAll(taskList.ToArray());
            }
    
            private static Foo Foo { get; } = new Foo();
        }

    以上代码开启了很多线程,每个线程都在尝试读写此结构体。每次写入的赋值都是在 A B C D 给定相同的一个数值,在读取的时候判断是否读取到的每一个属性是否都是相同的数值,如果存在不同的,那么证明给结构体赋值是线程不安全的

    运行以上代码,可以看到,在结构体中,存在属性的数值是不相同的。通过以上代码可以看到,放在类对象的字段的结构体,进行赋值是线程不安全的

    本文所有代码放在githubgitee 欢迎访问

    可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

    git init
    git remote add origin https://gitee.com/lindexi/lindexi_gd.git
    git pull origin 01a988dd6efdd0550ce0302ecbb93755f1720e85
    

    以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源

    git remote remove origin
    git remote add origin https://github.com/lindexi/lindexi_gd.git
    

    获取代码之后,进入 YanibeyeNelahallfaihair 文件夹

    我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

    如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入

    如有不方便在博客评论的问题,可以加我 QQ 2844808902 交流

    知识共享许可协议
    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

    展开全文
  • C语言结构体对象间直接赋值

    千次阅读 2017-08-03 10:20:29
    结构体也是变量(自定义变量),两个结构体之间直接赋值按道理应该也是可以的吧,说实话之前还从没遇到过将一个结构体对象赋值给另一个结构体对象的(见识太浅),那么下面做一个测试看看:#include "stdio.h"struct...

    C语言中变量间互相赋值很常见,例如:

    int a,b;
    a = b;

    结构体也是变量(自定义变量),两个结构体之间直接赋值按道理应该也是可以的吧,说实话之前还从没遇到过将一个结构体对象赋值给另一个结构体对象的(见识太浅),那么下面做一个测试看看:

    #include "stdio.h"
    
    struct test
    {
        int a;
        int b;
        int c;
        char *d;
    };
    
    int main()
    {
        struct test t1 = {1,2,3,"tangquan"};
        struct test t2 = {0,0,0,""};
        printf("%d,%d,%d,%s\r\n",t2.a,t2.b,t2.c,t2.d);
        t2 = t1;
        printf("%d,%d,%d,%s\r\n",t2.a,t2.b,t2.c,t2.d);
        return 0;
    }

    运行结果是:

    tq@ubuntu:/mnt/hgfs/vmshare$ gcc test.c -o tar
    tq@ubuntu:/mnt/hgfs/vmshare$ ./tar 
    0,0,0,
    1,2,3,tangquan

    很显然赋值之后t2结构体的内容全部赋值为了t1的内容,假设正确。那么C++中的类之间的相互赋值应该也是可以的了?

    展开全文
  • C语言中结构体直接赋值? 茫茫大士2018-10-21 10:47:2959954已收藏1 分类专栏:嵌入式文章标签:结构体c FROM:http://codewenda.com/c语言结构体直接赋值/ 在C语言中结构体变量之间可以进行赋值操作吗? 简单...

    C语言中结构体直接赋值?

    茫茫大士 2018-10-21 10:47:29  59954  已收藏 1

    分类专栏: 嵌入式 文章标签: 结构体 c

    FROM:http://codewenda.com/c语言结构体直接赋值/

    在C语言中结构体变量之间可以进行赋值操作吗?

    简单结构体的赋值

    先说结论:一般来说,C语言中的结构体变量可以用另一个变量对其进行赋值或初始化。简单结构体(不包含指针成员)直接赋值没有问题。
    我们先下面一段代码:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    #include <stdio.h>

    #include <stdlib.h>

     

    struct MyStruct

    {

        int a;

        int b;

        char c[10];

    };

     

    int main()

    {

        struct MyStruct t1 = {1, 2, "hello"};

        struct MyStruct t2 = {3, 4, "world"};

        t2 = t1; //将t1赋值给t2

        printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);

        printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);

     

        return 0;

    }

    以上代码的输出为:

    1

    2

    MyStruct t1: 1, 2, hello

    MyStruct t2: 1, 2, hello

    以上用t1给t2进行初始化,结果也相同。可以看到简单的结构体(结构体的成员没有指针成员)变量之间直接赋值是没有问题的。

    有指针成员的结构体赋值

    而通常情况下,稍微复杂一点的结构体里面会有指针成员,那么以上的浅拷贝则会有问题了,我们假设MyStruct里面的成员c不是数组,而是字符指针,会有什么问题呢?
    看如下代码:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

     

    struct MyStruct

    {

        int a;

        int b;

        char* c;

    };

     

    int main()

    {

        struct MyStruct t1;

        t1.a = 1;

        t1.b = 2;

        // 为指针区域赋值

        char *p = (char*)malloc(10*sizeof(char));

        strcpy(p, "hello");

        t1.c = p;

     

        struct MyStruct t2;

        t2 = t1;

        printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);

        // 释放了t1的内存

        // free(p);

        printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);

     

     

        printf("t1 pointer addr: %p\n", t1.c);

        printf("t2 pointer addr: %p\n", t2.c);

     

        return 0;

    }

    上面的输出结果为:

    1

    2

    3

    4

    MyStruct t1: 1, 2, hello

    MyStruct t2: 1, 2, hello

    t1 pointer addr: 0x6000284d0

    t2 pointer addr: 0x6000284d0

    可以看到,赋值会直接将t1的指针变量赋值给t2.c,如果我们在赋值之后将t1所用的资源释放掉,那么使用t2的话则可能导致内存泄漏了。如果上面的代码,我们没有注释掉 free(p);,那么输出t2时结果这不确定了:

    1

    2

    3

    4

    MyStruct t1: 1, 2, hello

    MyStruct t2: 1, 2, (/.?

    t1 pointer addr: 0x6000284d0

    t2 pointer addr: 0x6000284d0

     

    所以,如果struct中有指针成员,那么结构体赋值不能简单的直接复制了,而需要为指针成员另外分配内存,并将数据拷贝过去,当然我们可以将这些处理封装在单独的函数中来完成。
    示例代码如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    #include <stdio.h>

    #include <stdlib.h>

    #include <string.h>

     

    struct MyStruct

    {

        int a;

        int b;

        char* c;

    };

     

    int main()

    {

        struct MyStruct t1;

        t1.a = 1;

        t1.b = 2;

        // 为指针区域赋值

        char *p = (char*)malloc(10*sizeof(char));

        strcpy(p, "hello");

        t1.c = p;

     

        struct MyStruct t2;

        // 各个成员分别赋值,可以进行封装

        t2.a = t1.a;

        t2.b = t1.b;

        char *p2 = (char*)malloc(10*sizeof(char));

        strcpy(p2, t1.c);

        t2.c = p2;

     

        printf("MyStruct t1: %d, %d, %s\n", t1.a, t1.b, t1.c);

        // 释放了t1的内存

        free(p);

        printf("MyStruct t2: %d, %d, %s\n", t2.a, t2.b, t2.c);

        // 释放了t2的内存

        free(p2);

     

        printf("t1 pointer addr: %p\n", t1.c);

        printf("t2 pointer addr: %p\n", t2.c);

     

        return 0;

    }

    以上代码输出结果为:

    1

    2

    3

    4

    MyStruct t1: 1, 2, hello

    MyStruct t2: 1, 2, hello

    t1 pointer addr: 0x6000284d0

    t2 pointer addr: 0x600062e10

    展开全文
  • C语言对结构体进行赋值操作一、说明二、环境三、代码四、运行 一、说明 定义一个结构体: 并对其进行初始化操作,赋值操作,打印 1.注意, struct 定义的位置可以在main函数的外边 2.用的时候是 struct student ...

    C语言对结构体进行赋值操作

    一、说明

        定义一个结构体: 并对其进行初始化操作,赋值操作,打印
        1.注意, struct 定义的位置可以在main函数的外边
        2.用的时候是 struct student s1 //必须带着struct 要不然不认student为数据类型
        3.在定义结构体的时候不能对其进行初始化操作
        4.其他注意事项在注释里
    

    二、环境

    windows10
    MinGW64
    

    三、代码

    #include <stdio.h>
    #include <string.h>
    struct student
    {
        //注意一个中文占2B
        char name[50];
        int age; //这里不能对其进行赋值操作
        int sex;
    };
    void structPrintf(struct student s2);
    int main()
    {
        //下面进行初始化按顺序
        struct student s1 = {"在下涛涛", 20, 1};
        //DIY
        struct student s2 = {.age = 12, .name = "在下涛涛", .sex = 1};
        //这里证明了结构体的变量名字也是一个指针
        //且指向了结构体的首地址
        structPrintf(s1);
    
        //对s1进行修改
        printf("------s1进行改变---------\n");
        s1.age = 21;
        s1.sex = 0;
        //s1.name = "这样可以吗?";  //这里报错
        strcpy(s1.name, "使用函数进行改变");
        structPrintf(s1);
        printf("--通过scanf对s1进行改变---------\n");
        //数组赋值的时候,name就是首地址了
        scanf("%s", s1.name);
        //下面的就得取地址了
        scanf("%d", &s1.age);
        scanf("%d", &s1.sex);
        structPrintf(s1);
        return 0;
    }
    void structPrintf(struct student s2)
    {
        printf("name  = %s\n", s2.name);
        printf("age = %d\n", s2.age);
        if (s2.sex == 0)
        {
            printf("女\n");
        }
        else
        {
            printf("男\n");
        }
    }
    

    四、运行

    在这里插入图片描述

    展开全文
  • 深拷贝,拷贝后的两个对象互不影响干扰 二、示例 #include <iostream> typedef struct _Te_Resource_Param_ //定义两个字符数组,为了验证是深拷贝还是浅拷贝 { char pcPath[256]; char pcName[256]; }...
  • 结构体在程序设计语音中被广泛使用,在静态代码检测的时,对结构体变量进行区间运算的时候不能给出其明确的区间信息,会对其相关运算的判断精度造成影响,本文介绍了一种对结构体赋值运算的区间计算方法。首先,从抽象...
  • 结构体变量赋值

    2019-03-10 08:34:00
    在android的bootloader源码目录中,发现这个文件lk/app/aboot/aboot.c里面有一个关于结构体的定义,让我有点不太明白,哪位高手来解惑一下?struct atag_tcc_entry{char output;char resolution;};struct atag_tcc_...
  • 结构体指针赋值

    万次阅读 2017-02-17 15:10:02
    //方法1:可以给p分配一段内存空间,并使其指向此空间: #include main() { struct abc{ int a;}; struct abc *p; p=(struct abc *)malloc(sizeof(struct abc)...//方法2:可以让p指向一个已存在的内存空间:#i
  • Golang通过反射对结构体进行赋值和其他操作 通过反射可以方便快捷地访问Golang的结构体字段,并进行赋值或其他操作。 当两个结构体内容相同但名字不同时,如何快捷地进行赋值? 【或者内容有交集,对交集部分进行...
  • //构建结构体 struct Student { float sorce,a[1]; }stu[5]; int i; //主函数 int main(){ massagein(stu); avsorce(stu); massageout(stu); return 0; } //信息输入函数,循环输入五个学生...
  • struct Student { int s; }a; 这里声明a为全局; 为什么不可以在函数体外边 ...对a的成员进行赋值? 而 viod fun(){a.s=0;} 却可以? 这问题困惑我好久了,自始至终都没找到答案; 谁解释一下啊;
  • [我个人的广告: 欢迎观临我的个人网站 http://tuesland.com 图是蓝的,我的连载中短篇小说已经在 http://tuesland.com/liter 欢迎阅读]一直记得C语言中,结构体是不可以直接赋值的。我问了三个同学,都说在C++中...
  • c 结构体直接赋值

    千次阅读 2010-11-18 20:36:00
    通过对C语言的学习,相信大家都知道结构体能够直接赋值,但是如果结构体内部是数组,那情况又会如何呢? 结果是,还是能够直接赋值,且... //session 1:结构体能够作为一个对象返回 struct s_arra
  • struct student { char name[10]; int sore1,sore2,sore3; student(char a[10],int d,int b,int c) { strcpy(name,a); sore1=d; sore2=b;
  • 关注、星标公众号,直达精彩内容来源:技术让梦想更伟大作者:李肖遥最近在做通信协议的解析处理、传递分析等问题,总是遇到通信帧中的结构体拷贝等问题,遇到了一些坑,也是比较基础但是易错的C语言知...
  • trueValue.FieldByName("Num1").SetInt(123)//设置对象属性,注意这个一定要是真实的结构类型的reflect.Value才能调用,指针类型reflect.Value的会报错 //ptrValue.FieldByName("Num2").SetInt(23) trueValue....
  • 现在有两个A的对象,A haha =new A(); A hehe =new A(); haha.a =1; haha.b[0] =10; 现在希望把haha赋值给hehe, hehe =haha; 是可以做到赋值的,但发现有个问题,就是这样处理相当于是把hehe.b的指针指向...
  • 将外部相同类型的结构体赋值到共享内存中 崩溃。 1500个变量不会崩溃!2000就会崩溃了。   可能原因一: 是否使用了函数,并在函数中创建了较大的数组,造成栈溢出 可能原因二: 栈 拷贝到 共享内存 ...
  • http://blog.chinaunix.net/uid-24807808-id-3219820.html
  • 结构体对象

    千次阅读 2018-08-23 11:45:16
    结构体对象里面我们把值附上,这样就完成了一个结构体的对象。   如果我们要用到哪个结构体,我们就选择哪个,怎么选择呢,当然是使用他唯一而且不变的一个参数,name,ID等待。 把可以先把结构体的对象存到...
  • 结构体赋值

    2015-05-18 16:22:36
    c99的”.成员”赋值Test t = ...结构体可以直接赋值 C语言在相同类型的变量间赋值时是直接内存复制的,即将他们的内存进行复制。同样结构体变量,属于同一种变量,所以赋值时是按照他们的内存分布来直接拷贝的
  • 仔细看看是不是你的结构体忘记写 这样居然就不会报错了………… 有大神明白这到底是为什么吗?
  • 结论:非指针的赋值b=a; 是浅拷贝,b更改结构体里的数组响应的a中的数组也会改变,而指针n=&a;则是n指向了a,n怎么变,a就怎么变 #include #include typedef struct str { int *p; int date; }str; void pri(str...
  • 今天梳理下golang中结构体赋值、指针以及获取成员变量方式

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 62,611
精华内容 25,044
关键字:

结构体对象赋值