成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試:有時候還需要多些自信

企業動態
今天遇到了個面試,其中有的問題我當時還真不能確定,遂發出來,大家分享。

今天遇到了個面試,其中有的問題我當時還真不能確定,遂發出來,大家分享。

先大致講一下流程,一面還挺順利,游刃有余;二面就有些緊張了,是個額頭頭發不多但是顯得很精干的男士(下文簡稱為A)。

只摘錄其中的部分我很“為難”的地方:

A:string是值類型是引用類型?

ME:(我心想string是class,肯定是)引用類型

A:那我有個方法,參數為string,我在里面改變他的值,原來的會變嗎?

ME:(這個我當時很猶豫,雖說string平時用,但是還真考慮過這個。我要是說會不會變吧,豈不是自打嘴巴?String是引用類型,怎么還值專遞呢?)

       當時我就記得園子里有句話:String是引用類型,但是用起來像值類型。我就說的是不變。

下面上一段代碼分析一下:

static void Foo(string  s)
        {
            s 
= "bbb";
        }

string s = "aaa";
            Foo(s);
Console.WriteLine(s);
這個確實是不會變的,調用完之后還是“aaa”,這是為什么呢?
1 string s = "aaa";
 2 00000051 8B 05 88 20 C0 02 mov         eax,dword ptr ds:[02C02088h] 
 3 00000057 89 45 B8         mov         dword ptr [ebp-48h],eax 
 4     92:             Foo(s);
 5 0000005a 8B 4D B8         mov         ecx,dword ptr [ebp-48h] 
 6 0000005d E8 A6 AF D4 FF   call        FFD4B008 
 7 00000062 90               nop              
 8     93:             Console.WriteLine(s);
 9 00000063 8B 4D B8         mov         ecx,dword ptr [ebp-48h] 
10 00000066 E8 95 24 3F 67   call        673F2500 
11 
12 
13 
14 
15 
16  static void Foo(string  s)
17     82:         {
18 00000000 55               push        ebp  
19 00000001 8B EC            mov         ebp,esp 
20 00000003 57               push        edi  
21 00000004 56               push        esi  
22 00000005 53               push        ebx  
23 00000006 83 EC 30         sub         esp,30h 
24 00000009 33 C0            xor         eax,eax 
25 0000000b 89 45 F0         mov         dword ptr [ebp-10h],eax 
26 0000000e 33 C0            xor         eax,eax 
27 00000010 89 45 E4         mov         dword ptr [ebp-1Ch],eax 
28 00000013 89 4D C4         mov         dword ptr [ebp-3Ch],ecx 
29 00000016 83 3D E0 8C 7B 00 00 cmp         dword ptr ds:[007B8CE0h],0 
30 0000001d 74 05            je          00000024 
31 0000001f E8 1D 91 57 68   call        68579141 
32 00000024 90               nop              
33     83:             s = "bbb";
34 00000025 8B 05 90 20 C0 02 mov         eax,dword ptr ds:[02C02090h] 
35 0000002b 89 45 C4         mov         dword ptr [ebp-3Ch],eax 
36     84:         }
37 0000002e 90               nop              
38 0000002f 8D 65 F4         lea         esp,[ebp-0Ch] 
39 00000032 5B               pop         ebx  
40 00000033 5E               pop         esi  
41 00000034 5F               pop         edi  
42 00000035 5D               pop         ebp  
43 00000036 C3               ret              

可以看到第2行將字符串的地址寫入到 eax,然后寫到堆棧的【ebp-48h】處;

調用Foo方法前,放到ecx中。

在方法Foo中,可以看到又經ecx放到了【ebp-3Ch】處;

在執行s=“bbb”的時候,同樣將新字符串的地址放到了【ebp-3Ch】處,但是原來的字符串并為更改,只是更改了臨時變量s的引用。

所以在調用完方法Foo之后,原來的字符串還是“aaa”,沒有改變。

所以這個時候我回答不變是對的,但是我不知道為什么string的傳遞是類似于值傳遞的,有點運氣了。

接下來,他又問

A:那如果我有個類,里面有string成員,我同樣改變他的值,外面的會變嗎?這個時候我回答的是可以改變。

是不是這樣呢?同樣,上代碼:

1 class C1
 2     {
 3         public string s1="aaa";
 4     }
 5 
 6  static void Foo(C1   c1)
 7         {
 8             c1.s1  = "bbb";
 9         }
10 
11  C1 c1 = new C1();
12             Foo(c1);
13             Console.WriteLine(c1.s1 );

 

1  Foo(c1);
 2 0000006c 8B 4D B8         mov         ecx,dword ptr [ebp-48h] 
 3 0000006f E8 94 AF 7F FF   call        FF7FB008 
 4 00000074 90               nop              
 5     93:             Console.WriteLine(c1.s1 );
 6 00000075 8B 45 B8         mov         eax,dword ptr [ebp-48h] 
 7 00000078 8B 48 04         mov         ecx,dword ptr [eax+4
 8 0000007b E8 80 24 52 67   call        67522500 
 9 
10 
11 
12  static void Foo(C1   c1)
13     82:         {
14 00000000 55               push        ebp  
15 00000001 8B EC            mov         ebp,esp 
16 00000003 57               push        edi  
17 00000004 56               push        esi  
18 00000005 53               push        ebx  
19 00000006 83 EC 30         sub         esp,30h 
20 00000009 33 C0            xor         eax,eax 
21 0000000b 89 45 F0         mov         dword ptr [ebp-10h],eax 
22 0000000e 33 C0            xor         eax,eax 
23 00000010 89 45 E4         mov         dword ptr [ebp-1Ch],eax 
24 00000013 89 4D C4         mov         dword ptr [ebp-3Ch],ecx 
25 00000016 83 3D E0 8C 13 00 00 cmp         dword ptr ds:[00138CE0h],0 
26 0000001d 74 05            je          00000024 
27 0000001f E8 AD 90 6A 68   call        686A90D1 
28 00000024 90               nop              
29     83:             c1.s1  = "bbb";
30 00000025 8B 05 90 20 D7 02 mov         eax,dword ptr ds:[02D72090h] 
31 0000002b 8B 4D C4         mov         ecx,dword ptr [ebp-3Ch] 
32 0000002e 8D 51 04         lea         edx,[ecx+4
33 00000031 E8 9A 16 45 68   call        684516D0 
34     84:         }
35 00000036 90               nop              
36 00000037 8D 65 F4         lea         esp,[ebp-0Ch] 
37 0000003a 5B               pop         ebx  
38 0000003b 5E               pop         esi  
39 0000003c 5F               pop         edi  
40 0000003d 5D               pop         ebp  
41 0000003e C3               ret              

在執行30行的時候eax是01DBC268,其內存的內容拷貝出來是:

54 0b a0 67 04 00 00 00 03 00 00 00 62 00 62 00 62 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

可以看出這是一個string的實例,前面的67a00b54是MT的地址,后面的00000004是字符串的實際長度,00000003是字符串有效內容的長度,

后面的3個0062是連著三個字符‘b’,看來確實是字符串“bbb”。再后面00的就不管了。

接著依次執行31和32行,則ecx是01D9EEC8,edx是01D9EECC;據猜測ecx應該是c1的地址,把內存考出來看一下:

d0 99 41 00 94 ee d9 01 00 00 00 00 24 43 9d 67 0a 00 00 00 70 07 a0 67 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

而此時edx就應該是s1的地址,可以看出edx就比ecx相差4,所以01d9ee94就應該是字符串“aaa”的地址,同樣考出來看看:

54 0b a0 67 04 00 00 00 03 00 00 00 61 00 61 00 61 00 00 00 00 00 00

可以看出,“aaa”和“bbb”的頭幾個部分完全是一樣的,就是后面的一個是61,一個是62.

那么問題很簡單了,知道把c1里的字符串地址從01d9ee94換成01DBC268就算OK了。事實上33行就是做這個事情的。

看一下執行完33行后的c1的內容:

d0 99 41 00 68 c2 db 01 00 00 00 00 24 43 9d 67 0a 00 00 00 70 07 a0 67 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

可以看出,確實是換了。

所以到這里,問題解決了。

#p#

接著這老大又問

A:有沒有其他方法可以改變字符串?

ME:加ref或out關鍵字可以,或者用指針。

我們看一下加ref(或加out,其實是一樣的)的為什么可以改變,更詳細的看一下。

static void Foo(ref string  s)
        {
            s
= "bbb";
        }

string s = "aaa";
            Foo(
ref s);
            Console.WriteLine(s );

繼續匯編:

1  string s = "aaa";
 2 0000004c 8B 05 88 20 ED 02 mov         eax,dword ptr ds:[02ED2088h] 
 3 00000052 89 45 B8         mov         dword ptr [ebp-48h],eax 
 4     92:             Foo(ref s);
 5 00000055 8D 4D B8         lea         ecx,[ebp-48h] 
 6 00000058 E8 AB AF D0 FF   call        FFD0B008 
 7 0000005d 90               nop              
 8     93:             Console.WriteLine(s );
 9 0000005e 8B 4D B8         mov         ecx,dword ptr [ebp-48h] 
10 00000061 E8 9A 24 49 67   call        67492500 
11 
12 
13 
14   static void Foo(ref string  s)
15     82:         {
16 00000000 55               push        ebp  
17 00000001 8B EC            mov         ebp,esp 
18 00000003 57               push        edi  
19 00000004 56               push        esi  
20 00000005 53               push        ebx  
21 00000006 83 EC 30         sub         esp,30h 
22 00000009 33 C0            xor         eax,eax 
23 0000000b 89 45 F0         mov         dword ptr [ebp-10h],eax 
24 0000000e 33 C0            xor         eax,eax 
25 00000010 89 45 E4         mov         dword ptr [ebp-1Ch],eax 
26 00000013 89 4D C4         mov         dword ptr [ebp-3Ch],ecx 
27 00000016 83 3D E0 8C 6D 00 00 cmp         dword ptr ds:[006D8CE0h],0 
28 0000001d 74 05            je          00000024 
29 0000001f E8 1D 91 61 68   call        68619141 
30 00000024 90               nop              
31     83:             s= "bbb";
32 00000025 8B 05 90 20 ED 02 mov         eax,dword ptr ds:[02ED2090h] 
33 0000002b 8B 4D C4         mov         ecx,dword ptr [ebp-3Ch] 
34 0000002e 8D 11            lea         edx,[ecx] 
35 00000030 E8 A3 0E 3C 68   call        683C0ED8 
36     84:         }
37 00000035 90               nop              
38 00000036 8D 65 F4         lea         esp,[ebp-0Ch] 
39 00000039 5B               pop         ebx  
40 0000003a 5E               pop         esi  
41 0000003b 5F               pop         edi  
42 0000003c 5D               pop         ebp  
43 0000003d C3               ret              

同樣,關注代碼的32~34行:

eax:01DEC25C,內容:

54 0b a0 67 04 00 00 00 03 00 00 00 62 00 62 00 62 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

確實是字符串“bbb”

ecx和edx都是:05C7E778,內容:0x01dcee94,這個是字符串“aaa”的地址。

執行完35行之后,地址05C7E778的內容變成了01DEC25C,在之后第9行代碼確實地址變成了01DEC25C,則可以推斷05C7E778是上個堆棧

s引用的位置,則35行的代碼則是將新“bbb”的地址寫到原來的s引用處。

A繼續問:ref和out有什么區別?

ME:我說兩者沒什么區別,就是out不要求變量初始化。

A:那要是初始化了呢,改變了之后是什么值?

ME:(這個我還真被問住了。不知道可以,但是不能亂說啊。)基于對out這個關鍵字的理解,我認為應該返回改變后的值。

如果將原來的ref改為out,匯編代碼完全相似,區別就是變量是否初始化問題,如果不初始化,其實變量在棧中也是有位置的,只不過地址內容為0.

如果初始化,則和ref完全一樣。代碼我就不貼了,大家可以自己調式看一看。

問題:為什么默認的字符串作為參數傳遞是類似的值傳遞呢?請大家告訴我。

靠,弄了半天,才記得所有傳遞默認都是值傳遞,這才是問題的根源。老了,腦袋記不清了,以前看C語言的時候還特別注意了這點,結果還是忘記了。

問題的答案請看我最下面的留言。

在這里有些誤導大家了,給大家致歉。

【編輯推薦】

  1. 求職者看面試官:和不懂技術的人談技術
  2. 思科認證CCIE考試介紹:費用及實驗面試等
  3. 面試官:我如何招到聰明又能做事的人
責任編輯:張攀 來源: 博客園
相關推薦

2023-06-01 07:50:42

JSDocTypeScriptAPI

2022-11-02 08:55:43

Gofor 循環存儲

2025-05-28 01:10:00

SQL索引MySQL

2017-12-11 17:14:56

ERP管理數字化

2020-04-26 09:32:13

物聯網安全技術

2018-09-20 22:04:01

2024-11-26 07:37:22

2025-05-28 00:00:00

CSS前端Flexbox

2023-09-12 14:02:30

數組vector

2021-03-31 13:20:02

智慧城市物聯網5G

2024-10-14 08:39:25

2023-05-22 07:10:38

GPTpromptPerplexity

2010-03-16 16:47:58

Java編程語言

2023-01-31 17:24:21

DPUCPUGPU

2022-11-15 11:13:10

域名Linux文件

2022-12-12 08:17:29

2023-04-07 15:30:24

操作系統ChatGPT

2013-09-26 09:14:27

公有云云服務

2017-08-21 16:00:14

機器學習機器翻譯

2023-10-24 15:15:26

HTTPWebSocket
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜精品一区二区三区在线视频 | 天天躁日日躁xxxxaaaa | 精品国产一区二区三区久久 | 日本不卡一区 | 伊人精品一区二区三区 | 亚洲精品久久久久久久不卡四虎 | 欧美日韩在线视频一区二区 | 黄色骚片| 久久天天躁狠狠躁夜夜躁2014 | h小视频 | 欧美日韩高清一区 | 日韩在线观看网站 | 一区二区久久 | 成人国产精品久久 | 中文字幕亚洲一区 | 黄网址在线观看 | 奇米视频777 | 亚洲精久 | 国产精品一区久久久久 | 成人国产精品一级毛片视频毛片 | 国产日韩中文字幕 | 成人免费视频在线观看 | 日日天天 | 亚洲精品一 | 国产精品视频久久 | 亚洲精品中文在线 | 国产成人免费视频网站视频社区 | 国产伦精品一区二区三区在线 | 欧美精品一区二区三区蜜桃视频 | 精品乱码一区二区 | 欧美一区二区在线 | 精品视频一二区 | 成年免费在线观看 | 黄片毛片免费观看 | 日韩视频在线播放 | 亚洲一区欧美 | 亚洲午夜在线 | 亚洲一区二区三区在线视频 | 久久久一区二区三区四区 | 欧美一区二区三区在线播放 | 亚洲精品成人在线 |