深入浅出: C 与 C++ 中“结构直接复制”的探讨

[复制链接]
 楼主| highgear 发表于 2011-5-10 00:01 | 显示全部楼层 |阅读模式
本帖最后由 highgear 于 2011-5-10 00:05 编辑

结构直接复制 c 语言中使用的不多, 但在 c++ 却是一个热门,几乎每一本书,几乎每一个 c++ 程序员的面试都不可避免的提到结构直接复制的问题。我们现在来探讨结构直接复制在 c c++ 有什么异同,先来看看一段简单的程序:



  1. typedef struct SA
  2. {
  3.    char x;
  4. } A;

  5. void main (void) {
  6.     A a1, a2;
  7.     a1 = a2;
  8. }
复制代码



其中的 a1 = a2, 就是结构直接复制 c 中,这种方法优劣如何呢?来看看Keil C 生成的汇编代码:



  1. 14:         a1 = a2;
  2. C:0x0D07    7808     MOV      R0,#0x08
  3. C:0x0D09    7C00     MOV      R4,#0x00
  4. C:0x0D0B    7D00     MOV      R5,#0x00
  5. C:0x0D0D    7B00     MOV      R3,#0x00
  6. C:0x0D0F    7A00     MOV      R2,#0x00
  7. C:0x0D11    7909     MOV      R1,#0x09
  8. C:0x0D13    7E00     MOV      R6,#0x00
  9. C:0x0D15    7F01     MOV      R7,#0x01
  10. C:0x0D17    120C2C   LCALL    C?COPY(C:0C2C)
复制代码

可以看到,仅仅一个字节的复制,竟然使用了大量的代码,效率及其低下。而这段代码与Keil C memcpy 是一模一样的:




  1. 15:         memcpy(&a1, &a2, sizeof(A));
  2. C:0x0CF3    7808     MOV      R0,#0x08
  3. C:0x0CF5    7C00     MOV      R4,#0x00
  4. C:0x0CF7    7D00     MOV      R5,#0x00
  5. C:0x0CF9    7B00     MOV      R3,#0x00
  6. C:0x0CFB    7A00     MOV      R2,#0x00
  7. C:0x0CFD    7909     MOV      R1,#0x09
  8. C:0x0CFF    7E00     MOV      R6,#0x00
  9. C:0x0D01    7F01     MOV      R7,#0x01
  10. C:0x0D03    120C2C   LCALL    C?COPY(C:0C2C)
复制代码

这就是说,Keil C 结构直接复制简单的调用了 memcpy 8051 既没有 DMA, 也没有 block move/copy 之类的复制指令,因此 memcpy 的效率不会很高。


现在我们来看看 C++ 下面的表现,编译器使用 Borland C++, 同样的代码,Borland c++ 显然聪明了很多,仅仅生成了两条 8086 汇编指令:
      cs:026D 8A46FC mov   al,[bp-04]
     cs:0270 8846F8  mov   [bp-08],al

非常精简。 这样,没有什么比较性。我们现在稍微修改一下
typedef struct SA
{

char x[3];

} A;

此时,Borland C++ 同样生成了一大堆的代码:



  1. #TEST2#13:  a1 = a2;
  2.   cs:026D 8D46FC         lea    ax,[bp-04]
  3.   cs:0270 16             push   ss
  4.   cs:0271 50             push   ax
  5.   cs:0272 8D46F8         lea    ax,[bp-08]
  6.   cs:0275 16             push   ss
  7.   cs:0276 50             push   ax
  8.   cs:0277 B90300         mov    cx,0003
  9.   cs:027A E8D31E         call   N_SCOPY@
复制代码

我们可以得出一个结论,borland c++
结构直接复制的效率也不过如此。


等等!  结构(类)直接复制在 c++ 里大量的使用,难道没有一个更好的方法来实现么?比如:

a1.x[0] = a2.x[0];

a1.x[1] = a2.x[1];

a1.x[2] = a2.x[2];

或者,程序员只想复制其中一部分的数据,而不是像在 c 下用memcpy 全部复制?C++ 下有什么样的方法可以实现呢?

 楼主| highgear 发表于 2011-5-10 01:28 | 显示全部楼层
本帖最后由 highgear 于 2011-5-10 01:29 编辑

C++与 C 不同的一个地方是,结构(类)可以有成员函数,其中一个重要的部分是 拷贝构造函数。 这个函数顾名思义是利用 copy 来初始化结构(类)。现在加入一个拷贝构造函数到SA结构中,再来看看结果如何 :

typedef struct SA

{


char x[3];


SA(SA& sa) { x[0] = sa.x[0]; } //拷贝构造函数

} A;

void main (void) {

A a2;

      a2.x[0] = 1;

   A a1 = a2;

     a2 = a1;
}
8086汇编代码:

  1. #TEST2#19:  A a1 = a2;
  2.   cs:026D 8A46FC         mov    al,[bp-04]
  3.   cs:0270 8846F8         mov    [bp-08],al
  4. #TEST2#20:  a2 = a1;
  5.   cs:0273 8D46FC         lea    ax,[bp-04]
  6.   cs:0276 16             push   ss
  7.   cs:0277 50             push   ax
  8.   cs:0278 8D46F8         lea    ax,[bp-08]
  9.   cs:027B 16             push   ss
  10.   cs:027C 50             push   ax
  11.   cs:027D B90300         mov    cx,0003
  12.   cs:0280 E8C11E         call   N_SCOPY@
复制代码


我们发现 A a1 = a2 产生了所希望的精简代码, 但 a2 = a1, 却还是臃肿代码。这是怎么回事? 之间的区别是什么?


A a1 = a2, 由于 a1 处于构造阶段,所以会调用 拷贝构造函数 SA(SA& sa)
{ x[0] = sa.x[0]; }
, 而 a2 = a1 则调用了结构(类) 的默认 copy 函数。只要我们重载复制操作, 就可以让 a2 = a1 按照我们的意愿进行复制。


typedef struct SA

{


char x[3];



SA(SA& sa) { x[0] = sa.x[0]; } //拷贝构造函数



void operator=(SA& sa)
{ x[0] = sa.x[0]; }     //复制函数

} A;



此时,再看看 a2 = a1, 也产生了精简的代码。





结论:

1) Keil C 中, 结构直接复制使用了 memcpy 复制结构, 效率低下, 不建议使用。

2) C++ 中, 由于拷贝构造函数以及 = 重载的存在, 可以使用用户自己的复制函数,可以达到很高的效率

3) C++ 中, 要注意 A a1 = a2 与 a1 = a2 之间的不同。

4) C++ 中, 如果没有 拷贝构造函数或者 = 重载的存在, 默认的拷贝函数会被调用。








CC2530 发表于 2011-5-10 06:32 | 显示全部楼层
本帖最后由 CC2530 于 2011-5-10 11:21 编辑

楼主你的测试代码,定义了两个局部变量,然后在这两个局部变量赋值,
很多编译器,都会被认为是无效代码,最后编译出的代码一条指令都没有。

我稍微改动一下,使用全局变量。

看看其他编译器:
  1. typedef struct SA
  2. {
  3.    char x;
  4. } A;

  5. A a1, a2;
  6.    
  7. void test (void)
  8. {
  9.     a1 = a2;
  10. }
复制代码
IAR 8051 7.60:
  1.         RSEG NEAR_CODE:CODE:NOROOT(0)
  2. //   17 void test (void)
  3. test:
  4. //   18 {
  5.         ; Auto size: 0
  6.         ; Saved register size: 0
  7. //   19     a1 = a2;
  8.         MOV     R0,#a2
  9.         MOV     R1,#a1
  10.         MOV     A,#0x1
  11.         LCALL   ?MOVE_LONG8_IDATA_IDATA
  12. //   20 }
  13.         RET
复制代码
IAR AVR 5.51:
  1.         RSEG CODE:CODE:NOROOT(1)
  2. //   11 void test (void)
  3. test:
  4. //   12 {
  5. //   13     a1 = a2;
  6.         LDS     R16, (a1 + 1)
  7.         STS     a1, R16
  8. //   14 }
  9.         RET
复制代码
WinAVR 2010:

  1. void test (void)
  2. {
  3.     a1 = a2;
  4.   5a: 80 91 01 01  lds r24, 0x0101
  5.   5e: 80 93 00 01  sts 0x0100, r24
  6. }
  7.   62: 08 95        ret

复制代码
IAR 430 5.20
  1.         RSEG CODE:CODE:REORDER:NOROOT(1)
  2. //   17 void test (void)
  3. test:
  4. //   18 {
  5. //   19     a1 = a2;
  6.         MOV.B   &a2, &a1
  7. //   20 }
  8.         RET
复制代码
IAR ARM 5.41

  1.         SECTION `.text`:CODE:NOROOT(1)
  2.         THUMB
  3. //   21 void test (void)
  4. //   22
  5. //   23 {
  6. //   24
  7. //   25     a1 = a2;
  8. test:
  9.         LDR.N    R0,??DataTable0  ;; a1
  10.         LDR      R1,[R0, #+4]
  11.         STR      R1,[R0, #+0]
  12. //   26
  13. //   27 }
  14.         BX       LR               ;; return
复制代码
IAR STM8 1.3

  1.         SECTION `.near_func.text`:CODE:REORDER:NOROOT(0)
  2.         CODE
  3. //    8 void test (void)
  4. //    9 {
  5. //   10   
  6. //   11     a1 = a2;
  7. test:
  8.         LD        A, L:a2
  9.         LD        L:a1, A
  10. //   12 }
  11.         RET
复制代码
测试的编译器中,仅仅只有IAR 8051也是调用RAM复制函数,其他编译器都是直接复制。

评分

参与人数 1威望 +1 收起 理由
highgear + 1

查看全部评分

SLEET1986 发表于 2011-5-10 07:59 | 显示全部楼层
关注中--
ayb_ice 发表于 2011-5-10 08:23 | 显示全部楼层
标准的就是调用内存COPY程序
原野之狼 发表于 2011-5-10 08:44 | 显示全部楼层
LZ不但精通C 还精通C++
学习ing...
CC2530 发表于 2011-5-10 10:46 | 显示全部楼层
本帖最后由 CC2530 于 2011-5-10 11:05 编辑

c++ 我也来试试:
测试代码改成:
  1. typedef struct SA
  2. {
  3.    char x;
  4. } A;

  5. A a1, a2;

  6. void test1 (void)
  7. {
  8.         a1 = a2;
  9. }

  10. void test2 (void)
  11. {
  12.         A a1, a2;
  13.         a1 = a2;
  14. }
复制代码
C++Builder 2009
  1. File1.cpp.23: void test1 (void)
  2. 00401168 55               push ebp
  3. 00401169 8BEC             mov ebp,esp
  4. File1.cpp.25: a1 = a2;
  5. 0040116B A075214000       mov al,[$00402175]
  6. 00401170 A274214000       mov [$00402174],al
  7. File1.cpp.26: }
  8. 00401175 5D               pop ebp
  9. 00401176 C3               ret
  10. 00401177 90               nop
  11. File1.cpp.28: void test2 (void)
  12. 00401178 55               push ebp
  13. 00401179 8BEC             mov ebp,esp
  14. 0040117B 51               push ecx
  15. File1.cpp.31: a1 = a2;
  16. 0040117C 8A45FE           mov al,[ebp-$02]
  17. 0040117F 8845FF           mov [ebp-$01],al
  18. File1.cpp.32: }
  19. 00401182 59               pop ecx
  20. 00401183 5D               pop ebp
  21. 00401184 C3               ret
复制代码
VC 2008

  1. void test1 (void)
  2. {
  3. 004113B0  push        ebp  
  4. 004113B1  mov         ebp,esp
  5. 004113B3  sub         esp,0C0h
  6. 004113B9  push        ebx  
  7. 004113BA  push        esi  
  8. 004113BB  push        edi  
  9. 004113BC  lea         edi,[ebp-0C0h]
  10. 004113C2  mov         ecx,30h
  11. 004113C7  mov         eax,0CCCCCCCCh
  12. 004113CC  rep stos    dword ptr es:[edi]
  13. a1 = a2;
  14. 004113CE  mov         al,byte ptr [a2 (417140h)]
  15. 004113D3  mov         byte ptr [a1 (417141h)],al
  16. }
  17. 004113D8  pop         edi  
  18. 004113D9  pop         esi  
  19. 004113DA  pop         ebx  
  20. 004113DB  mov         esp,ebp
  21. 004113DD  pop         ebp  
  22. 004113DE  ret  
  23. void test2 (void)
  24. {
  25. 004113F0  push        ebp  
  26. 004113F1  mov         ebp,esp
  27. 004113F3  sub         esp,0D8h
  28. 004113F9  push        ebx  
  29. 004113FA  push        esi  
  30. 004113FB  push        edi  
  31. 004113FC  lea         edi,[ebp-0D8h]
  32. 00411402  mov         ecx,36h
  33. 00411407  mov         eax,0CCCCCCCCh
  34. 0041140C  rep stos    dword ptr es:[edi]
  35. A a1, a2;
  36. a1 = a2;
  37. 0041140E  mov         al,byte ptr [a2]
  38. 00411411  mov         byte ptr [a1],al
  39. }
  40. 00411414  push        edx  
  41. 00411415  mov         ecx,ebp
  42. 00411417  push        eax  
  43. 00411418  lea         edx,[ (41142Ch)]
  44. 0041141E  call        @ILT+140(@_RTC_CheckStackVars@8) (411091h)
  45. 00411423  pop         eax  
  46. 00411424  pop         edx  
  47. 00411425  pop         edi  
  48. 00411426  pop         esi  
  49. 00411427  pop         ebx  
  50. 00411428  mov         esp,ebp
  51. 0041142A  pop         ebp  
  52. 0041142B  ret   
复制代码
IAR AVR 5.51 C++

  1.         RSEG CODE:CODE:NOROOT(1)
  2. //   13 void test1 (void)
  3. ??test1:
  4. //   14
  5. //   15 {
  6. //   16
  7. //   17         a1 = a2;
  8.         LDS     R16, (a1 + 1)
  9.         STS     a1, R16
  10. //   18
  11. //   19 }
  12.         RET
  13. //   20
  14. //   21
  15. //   22
  16.         RSEG CODE:CODE:NOROOT(1)
  17. //   23 void test2 (void)
  18. ??test2:
  19. //   24
  20. //   25 {
  21. //   26
  22. //   27         A a1, a2;
  23. //   28
  24. //   29         a1 = a2;
  25. //   30
  26. //   31 }
  27.         RET
复制代码
IAR ARM 5.41 C++

  1.         SECTION `.text`:CODE:NOROOT(1)
  2.         THUMB
  3. //   15 void test1 (void)
  4. //   16
  5. //   17 {
  6. //   18
  7. //   19         a1 = a2;
  8. _Z5test1v:
  9.         LDR.N    R0,??DataTable0  ;; a1
  10.         LDR      R1,[R0, #+4]
  11.         STR      R1,[R0, #+0]
  12. //   20
  13. //   21 }
  14.         BX       LR               ;; return
  15.         SECTION `.text`:CODE:NOROOT(2)
  16.         DATA
  17. ??DataTable0:
  18.         DC32     a1
  19. //   22
  20. //   23
  21. //   24
  22.         SECTION `.text`:CODE:NOROOT(1)
  23.         THUMB
  24. //   25 void test2 (void)
  25. //   26
  26. //   27 {
  27. //   28
  28. //   29         A a1, a2;
  29. //   30
  30. //   31         a1 = a2;
  31. //   32
  32. //   33 }
  33. _Z5test2v:
  34.         BX       LR               ;; return
复制代码
IAR 430 5.20 C++

  1.         RSEG CODE:CODE:REORDER:NOROOT(1)
  2. //   15 void test1 (void)
  3. ??test1:
  4. //   16
  5. //   17 {
  6. //   18
  7. //   19         a1 = a2;
  8.         MOV.B   &a2, &a1
  9. //   20
  10. //   21 }
  11.         RET
  12. //   22
  13. //   23
  14. //   24
  15.         RSEG CODE:CODE:REORDER:NOROOT(1)
  16. //   25 void test2 (void)
  17. ??test2:
  18. //   26
  19. //   27 {
  20. //   28
  21. //   29         A a1, a2;
  22. //   30
  23. //   31         a1 = a2;
  24. //   32
  25. //   33 }
  26.         RET
复制代码


IAR STM8 1.3 C++

  1.         SECTION `.near_func.text`:CODE:REORDER:NOROOT(0)
  2.         CODE
  3. //   15 void test1 (void)
  4. //   16
  5. //   17 {
  6. //   18
  7. //   19         a1 = a2;
  8. _Z5test1v:
  9.         LD        A, L:a2
  10.         LD        L:a1, A
  11. //   20
  12. //   21 }
  13.         RET
  14. //   22
  15. //   23
  16. //   24
  17.         SECTION `.near_func.text`:CODE:REORDER:NOROOT(0)
  18.         CODE
  19. //   25 void test2 (void)
  20. //   26
  21. //   27 {
  22. //   28
  23. //   29         A a1, a2;
  24. //   30
  25. //   31         a1 = a2;
  26. //   32
  27. //   33 }
  28. _Z5test2v:
  29.         RET
复制代码
CC2530 发表于 2011-5-10 11:08 | 显示全部楼层
本帖最后由 CC2530 于 2011-5-10 11:21 编辑

WinAVR 2009 C++
  1. 000000d8 <_Z5test1v>:

  2. void test1 (void)

  3. {

  4.         a1 = a2;
  5.   d8:        80 91 01 01         lds        r24, 0x0101
  6.   dc:        80 93 00 01         sts        0x0100, r24

  7. }
  8.   e0:        08 95               ret

  9. 000000e2 <_Z5test2v>:

  10.         A a1, a2;

  11.         a1 = a2;

  12. }
  13.   e2:        08 95               ret
复制代码
IAR 8051 7.60 C++

  1.         RSEG NEAR_CODE:CODE:NOROOT(0)
  2. //   15 void test1 (void)
  3. ??test1:
  4. //   16
  5. //   17 {
  6.         PUSH    DPL
  7.         PUSH    DPH
  8.         ; Saved register size: 2
  9.         ; Auto size: 0
  10. //   18
  11. //   19         a1 = a2;
  12.         MOV     DPTR,#a2
  13.         MOV     R4,#(a1 & 0xff)
  14.         MOV     R5,#((a1 >> 8) & 0xff)
  15.         MOV     A,#0x1
  16.         LCALL   ?MOVE_LONG8_XDATA_XDATA
  17. //   20
  18. //   21 }
  19.         POP     DPH
  20.         POP     DPL
  21.         RET
  22. //   22
  23. //   23
  24. //   24
  25.         RSEG NEAR_CODE:CODE:NOROOT(0)
  26. //   25 void test2 (void)
  27. ??test2:
  28. //   26
  29. //   27 {
  30.         ; Saved register size: 0
  31.         ; Auto size: 0
  32. //   28
  33. //   29         A a1, a2;
  34. //   30
  35. //   31         a1 = a2;
  36. //   32
  37. //   33 }
  38.         RET
复制代码
仅仅只有IAR 8051 C++才调用了RAM复制函数,其他都是直接复制。

评分

参与人数 1威望 +1 收起 理由
highgear + 1

查看全部评分

刘前辈 发表于 2011-5-10 18:48 | 显示全部楼层
本帖最后由 刘前辈 于 2011-5-10 19:29 编辑

LZ 花时间这个研究值得敬佩。我赞同5楼ayb_ice:标准的就是调用内存COPY程序。C语言大量的库函数就是让用户调用的,C语言教材最形象的说法就是“写C程序就是拎个麻袋,一麻袋C库函数,然后从麻袋里找需要的C模块,来搭建我们希望的建筑。”最好的建筑师才不知道什么水泥砂浆比例,砖头成分,钢筋号……这种事农民工都知道,谁都能做,建筑师关心的是大多数人不知道的事,他是金字塔最上层的人。

    所以,复制一个字节的结构,可以找高中生去写:汇编,C语句都行。而现在要求:复制一个10,000字节的结构或者文件!
    自己写for还是while ?不用,a1=a2; 一分钟不要,很简单就完成了。用不着C++ ,杀**何需宰牛刀?


代码开销:和复制1字节一样。282字节。当然时间可能不一样,C51拷贝什么都是逐字节来的。反正C51上感觉不到,和复制1字节一样快。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
刘前辈 发表于 2011-5-10 19:24 | 显示全部楼层
本帖最后由 刘前辈 于 2011-5-10 20:02 编辑

多说2句,“比较是在对等的平台上进行的。”86处理器有串拷贝语句,连DMA都不用,就2条汇编内部就完成了。
    那么是不是就可以说:
   “你那C51太差了,应该换86处理器!”(那没有可比性呀。)
    “谁用结构拷贝而不用memcpy( ),赶出论坛。”(玩笑一下,LZ终于自己证明,2者完全一样。终于给我平反了。)
    “结构拷贝从来不是为C准备的……我C+++……”请见《C与指针》P156

看来我第一个用C51,或者franklin C 实现了C++ 功能,能以简代繁,是很得意,看上去很欣赏的一件事。

举个例子,CAN总线模块初始化需要写10个以上功能寄存器,不得不把C像汇编那样一个一个寄存器写,无论中国,外国,学生,教授,什么书上都是这么耐心设置的;仅初始化语句,就要写满一页纸。利用结构拷贝, char arr[]={初始化数据);然后定义好CAN模块功能寄存器区指针,一条赋值语句就完成了。这是从内部RAM 通过总线 向外部Xdata 复制数据。如果说51系列MCU没有DMA,所以效率低下,由此推论刘前辈水平信息太落后,“你怎么不用带DMA的带CAN通信处理器的MCU芯片?”

        呵呵,LZ 知道有这种芯片?  给俺刘前辈推荐一下,重谢。 ( 可别推荐俺拿工控机代替嵌入式MCU,体积太大塞不进去。咱也搬不动。)


、、
cecwxf 发表于 2011-5-10 21:36 | 显示全部楼层
 楼主| highgear 发表于 2011-5-10 21:39 | 显示全部楼层
特别感谢 CC2530 的补充。
.
.
.
10楼的逻辑能力实在不敢让人恭维。
“我第一个用C51,或者franklin C 实现了C++ 功能", 我家的狗都把牙笑掉了。

技术归技术:
1) “比较是在对等的平台上进行的”, 同样的硬件平台, Borland C++ 对于 a1 = a2 结构直接复制代码效率远远不如 visual C++, Visual C++ 始终可以产生堪比手工的高效代码,不论结构的大小,从1字节到1000字节,这点 cc2530 可以证明。看上去 Keil C 在结构直接复制方面没有做任何优化,比其他同类的编译器也有所不如。因此这不是平台问题,而是编译器的问题,更是程序员的问题。


2)“谁用结构拷贝而不用memcpy( ),赶出论坛。”哈哈,10楼以前恐怕不知道 Keil C 对待结构拷贝就是直接调用 memcpy 吧?在 C 中使用 结构拷贝 等于把控制权交给了编译器, 而使用 memcpy 则由自己掌握,任何一个程序员都不会为一个字节的结构使用 memcpy, 但使用 结构拷贝 却可能因此产生臃肿的代码。

Keil上的一个高手关于结构复制说得在理:
“That's the trade-off: either write it yourself, and know what's going on, or go for convenience and delegate the control to the compiler.
You can't have it both ways, I'm afraid”
这就是交换:要么自己写,你知道会发生什么,要么选择便利而把控制权交给编译器。你不会二者得兼。
.
.
.
二者得兼的问题在C++中得到了很好的解决,可以利用拷贝构造和赋值重载来实现 write it yourself,同时,一些编译器像visual C++, 其默认的结构拷贝所产生的代码效率足够让程序员 go for convenience and delegate the control to the compiler。

这个问题的本质不是在于是否使用结构拷贝,而是在于是否有一种严谨认真的技术态度。
CC2530 发表于 2011-5-10 22:13 | 显示全部楼层
还有一个方面需要考虑。

结构体整体赋值,如果结构体比较小。一般编译器会直接把结构体优化到寄存器。
但是,如果对结构体使用memcpy操作,则结构体不能优化到寄存器。

评分

参与人数 2威望 +2 收起 理由
刘前辈 + 1
highgear + 1

查看全部评分

 楼主| highgear 发表于 2011-5-10 22:29 | 显示全部楼层
同意 13 楼。这一点上,Visual C 做的很好,而Keil C 则不管大小,直接调用 memcpy, 导致结构体整体赋值在Keil C 下的代码效率低下。看 3楼 给出的汇编代码, IAR 也比 Keil C 强不少。
刘前辈 发表于 2011-5-11 10:40 | 显示全部楼层
本帖最后由 刘前辈 于 2011-5-11 19:59 编辑

再次提醒所长:“比较是在对等的平台上。”

比Keil C51功能强的C多了,工控机功能比嵌入式MCU强多了,可惜,体积太大,我机顶盒塞不进去。
    所长今年54岁,我30岁,所长年龄功能比俺强不少,岂止不少呀,儿子都快比我年龄功能强了。

送你一张图,除了keil C51,你用什么C都无法给这个环形网上的节点编程。这种环境下:Keil C51是最强的。一览众山小。

    这么简单的道理,54岁的人都不懂?任何东西“存在的,就是合理的。”例如俺30岁,现场总线玩的很转,你所长玩一辈子,行吗?
     ——但是我由此就贬低你。说你54岁白活了,行吗?

     下面看图:1964年,荷兰人.Olof   Soderblom  发明了令牌环形网络,IBM当时以500万美元买断了这项专利。从此,IBM的大型机环形网和 Xeror  的以太网谁优谁劣的争论从未停止……( 其实一样,在各自的应用领域,都有各自最适合的。没有任何一项技术是在所有领域里通吃的!根本无意义的争论。)








、、

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
刘前辈 发表于 2011-5-11 11:01 | 显示全部楼层
所长知道的东西都是大多数人知道的。

多说一句不好听的:你不懂的东西还多呢。

当然我也一样。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
gouki_s 发表于 2011-5-11 12:03 | 显示全部楼层
这玩意儿的关键,是你需不需要内存中再有一份该结构的拷贝。
如果需要,那就老老实实copy吧,是memcpy还是for区别不大

评分

参与人数 1威望 +1 收起 理由
刘前辈 + 1

查看全部评分

刘前辈 发表于 2011-5-11 12:42 | 显示全部楼层
本帖最后由 刘前辈 于 2011-5-11 17:29 编辑

支持LS;只要需要就老老实copy,无论整体赋值还是调用 memcpy 区别不大,甚至完全一样。谁也不会为这一条功能语句的效率问题去换MCU 和 编译器 或者 C++ 。

LZ作为研究可以让我们这些菜鸟开开眼;就是别以否定他人的方式来抬高自己,萝卜白菜,各有所爱。这世界是多元的。你无法强迫别人和你一样观点,这属于典型的“强迫症”症状,劝所长去看看心理医生。真话,我没有恶意。旁观者清,你今年比去年症状明显厉害多了。( 例如,凡事要和别人比较个高下,否则心里就不舒服。最后不惜逻辑混乱,偏要占个上风。——去看看心理学的书,这叫什么心理障碍……书里讲得特清楚。)

     举个例子,您前几天还拿着 memcpy() 说事,大加赞赏,用来压制结构拷贝观点。没过几天,又把自己out了。又来C++了。我知道,再过几天,您一定会用C#说事。您自己有没有觉得不正常?

      13楼分明在说结构复制的优点,你怎么投了赞成票?你不是“谁用结构复制,赶出论坛!”么?立场左右漂移,不知道你到底想说什么,目的是什么。逻辑思维有些混乱,……心理问题?


、、
 楼主| highgear 发表于 2011-5-11 21:02 | 显示全部楼层
刘工你的脑袋进水了,还是被门夹过了?

令牌环与结构拷贝有什么关系?刘工你机顶盒塞不进去, 与此帖有什么关系?我既不是你爹,也不是你老师,你的技术难题与我也没有任何关系。刘工你这种行为是不够自信的表现,为非是让人知道刘工你不是水平很差,如此而已。

我想我的帖子把 结构复制 已经说的清清楚楚,明明白白。我的c++程序大量的使用结构复制,我只是不赞成胡乱应用 结构复制, 特别是在 keil c 中,或者比如一个 把一个 memcpy 的函数(https://bbs.21ic.com/icview-233103-1-1.html),用 结构复制来实现。同时,对所谓的“填补空白”“第一”等感到极为可笑。

再者,我不是所长,不能也不打算为所长辩护,所以,也请刘公拿出点男人的气度,尊重无法为自己辩护的所长。如果,刘公下面还是这样,我就会就结构拷贝一道算法题提出公开 PK,只是不知刘公有没有勇气。
 楼主| highgear 发表于 2011-5-11 21:16 | 显示全部楼层
17楼:不仅仅如此。
实际上,复制问题是一个相当复杂的问题。结构copy与memcpy 只是简单的“浅复制“,当结构(类)中包含对象指针的时候,浅复制仅仅复制了指针,而不会复制指针所指向的内容,比如字符串。所以在一些编译器提出了一个 clone 说法,即”深复制“。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

1222

帖子

61

粉丝
快速回复 在线客服 返回列表 返回顶部