C語言中結構體賦值問題的討論

2022-03-27 00:54:42 字數 2950 閱讀 7731

今天幫師姐調乙個程式的bug,師姐的程式中有個結構體直接賦值的語句,在我印象中結構體好像是不能直接賦值的,正如陣列不能直接賦值那樣,我懷疑這個地方有問題,但最後證明並不是這個問題。那麼就總結一下c語言中結構體賦值的問題吧:

下面是乙個例項:

#include 

struct

foofoo1

,foo2

;//define two structs with three different fields

void

struct_assign

(void

)int

main

()

我在ubuntu 13.04下使用gcc 4.7.3 編譯執行得到的結果,如下所示:

guohl@guohailin:~/documents/c$ gcc struct_test1.c -o struct_test1

guohl@guohailin:~/documents/c$ ./struct_test1

a 1 3.140000

可以從結果上看出,結構體直接賦值在c語言下是可行的,我們看看struct_assign()函式的彙編實現,從而從底層看看c語言是如何實現兩個結構體之間的賦值操作的:

struct_assign:

pushl

%ebp

movl

%esp,%

ebpmovl

foo1,%

eaxmovl

%eax

,foo2

//copy

thefirst

4byte

sfrom

foo1

tofoo2

movl

foo1+4

,%eaxmovl

%eax

,foo2+4

//copy

thesecond

4byte

sfrom

foo1

tofoo2

movl

foo1+8

,%eaxmovl

%eax

,foo2+8

//copy

thethird

4byte

sfrom

foo1

tofoo2

movl

foo1+12

,%eaxmovl

%eax

,foo2+12

//copy

theforth

4byte

sfrom

foo1

tofoo2

popl

%ebp

ret

這段彙編比較簡單,由於結構體的對齊的特性,sizeof(srtruct foo)=16,通過四次movl操作將foo1的結構體內容拷貝到結構體foo2中。從彙編上看出,結構體賦值,採用的類似於memcpy這種形式,而不是逐個欄位的拷貝。

如果結構體中含有其它複雜資料型別呢,例如陣列、指標、結構體等,從上面的彙編實現可以看出,只要兩個結構體型別相同,就可以實現賦值,如下例:

#include 

struct

foofoo1

,foo2

;int

main

()

執行結果如下:

guohl@guohailin:~/documents/c$ gcc struct_test2.c -o struct_test2

guohl@guohailin:~/documents/c$ ./struct_test2

1 2.000000 3.000000 abc

可以看出結果和我們想象的是一樣的。再次驗證結構體的賦值,是直接結構體的記憶體的拷貝!但正是這個問題,如上面的例項,foo1 和 foo2 中p_c 指標都是指向我們申請的一塊大小為4個位元組的記憶體區域,這裡注意的是,結構體的拷貝只是淺拷貝,即指標p_c的賦值並不會導致再申請一塊記憶體區域,讓foo2的p_c指向它。那麼,如果釋放掉foo1中的p_c指向的記憶體,此時foo2中p_c變成野指標,這是對foo2的p_c操作就會出現一些不可預見的問題!在c++中引入了一種可以允許使用者過載結構體賦值操作運算,那麼我們就可以根據語義過載賦值操作。

二等公民在維基百科上的解釋是:

二等公民不是乙個正式的術語,用來描述乙個社會體系內對一部分人的歧視或對外來人口的政治限制,即使他們作為乙個公民或合法居民的地位。 二等公民雖然不一定是奴隸或罪犯,但他們只享有有限的合法權利、公民權利和經濟機會,並經常受到虐待或忽視。法律無視二等公民,不向他們提供保護,甚至在制訂法律時可能會根本不考慮他們的利益。劃分出二等公民的行為,普遍被視為一種侵犯人權的行為。 典型的二等公民所面臨的障礙包括但不僅限於(缺乏或喪失表決權):權利被剝奪,限制民事或軍事服務(不包括任何情況下的徵兵),以及限制,語言,宗教,教育,行動和結社的自由,**的所有權,婚姻,性別認同和表達,住房和財產所有權 。

從詞條上解釋可以看出二等公民與一等公民在權利上是有差別的,這個詞很有意思作為計算機專業術語,其含義也有異曲同工之妙!同樣我們看看維基百科對計算機的術語」first-class citizen"(一等公民)的定義,一般要滿足以下幾點,

對比著上面的定義來看c語言陣列,陣列作為乙個函式的引數傳遞時,退化成乙個指標; 同時,陣列無法作為函式的返回值; 也許讓陣列更不服氣的是,陣列之間不能直接賦值操作,如下面的操作就是非法的:

inta[

10];

intb[10

];a=b

;

但是如果陣列包裝在結構體中,那麼就能進行賦值了!相比之下,結構體可以作為函式引數和返回值,這就是一等公民的待遇!至於為什麼陣列必須是二等公民,這是有歷史原因的,大家可以參考c 語言的發展史來看,有時間這塊內容我再補上!

C語言中結構體賦值問題的討論

今天幫師姐調乙個程式的bug,師姐的程式中有個結構體直接賦值的語句,在我印象中結構體好像是不能直接賦值的,正如陣列不能直接賦值那樣,我懷疑這個地方有問題,但最後證明並不是這個問題。那麼就總結一下c語言中結構體賦值的問題吧 下面是乙個例項 include struct foofoo1 foo2 def...

C語言中結構體賦值的討論

今天幫師姐調乙個程式的bug,師姐的程式中有個結構體直接賦值的語句,在我印象中結構體好像是不能直接賦值的,正如陣列不能直接賦值那樣,我懷疑這個地方有問題,但最後證明並不是這個問題。那麼就總結一下c語言中結構體賦值的問題吧 下面是乙個例項 include struct foofoo1 foo2 def...

c語言結構體賦值問題

對於結構體賦值問題 1 static psl 我過去一般會對結構體這樣賦值 static psl pslname 記住有一點,b 後面的逗號可有可無,至於具體為什麼,我只能理解自己能力還不夠。現在只知道可有可無。上面這種賦值方式是對的。看看下面的一種賦值方式 static psl pslname 這...