<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          淺談一下嵌入式中的強符號和弱符號

          共 2377字,需瀏覽 5分鐘

           ·

          2022-07-13 11:36

          __attribute__  是一個編譯器指令,其實是 GNU C 的一種機制,本質(zhì)是一個編譯器的指令,在聲明的時候可以提供一些屬性,在編譯階段起作用,來做多樣化的錯誤檢查和高級優(yōu)化。

          用于在 C、C++、Objective-C 中修飾變量、函數(shù)、參數(shù)、方法、類等。

          合理使用  __attribute__ 有什么好處?

          給編譯器提供上下文,幫助編譯器做優(yōu)化,合理使用可以收到顯著的優(yōu)化效果。編譯器會根據(jù)  __attribute__ 產(chǎn)生一些編譯警告,使代碼更規(guī)范。給代碼閱讀者提供必要的注解,助其理解代碼意圖。

          總之, __attribute__ 起到了給編譯器提供上下文的作用,如果錯誤的使用 __attribute__ 指令,因為給編譯器提供了錯誤的上下文,由此引起的錯誤通常很難被發(fā)現(xiàn)。

          強符號和弱符號

          在同一作用域下不能定義同一個變量或函數(shù),很多C語言學習者都理所當然地這么認為。

          這個其實是是有所偏頗的,GNU C對標準C語言進行了擴展,在GCC中,對于符號(在編譯時,變量和函數(shù)都被抽象成符號)而言,存在著強符號和弱符號之分。是的,是否支持這個特性是由不同的C語言標準決定的。

          對于C/C++而言,編譯器默認函數(shù)和已初始化的全局變量為強符號,而未初始化的全局變量為弱符號,在編程者沒有顯示指定時,編譯器對強弱符號的定義會有一些默認行為,同時開發(fā)者也可以對符號進行指定,使用"attribute((weak))"來聲明一個符號為弱符號。

          定義一個相同的變量,當兩者不全是強符號時,gcc在編譯時并不會報錯,而是遵循一定的規(guī)則進行取舍:

          • 當兩者都為強符號時,報錯:redefinition of 'xxx'
          • 當兩者為一強一弱時,選取強符號的值
          • 當兩者同時為弱時,選擇其中占用空間較大的符號,這個其實很好理解,編譯器不知道編程者的用意,選擇占用空間大的符號至少不會造成諸如溢出、越界等嚴重后果。
          • 在默認的符號類型情況下,強符號和弱符號是可以共存的,類似于這樣:
          int x;
          int x = 1;

          編譯不會報錯,在編譯時x的取值將會是1.

          但是使用 __attribute__((weak)) 將強符號轉換為弱符號,卻不能與一個強符號共存,類似于這樣:

          int __attribute__((weak)) x = 0;
          int x = 1;

          編譯器將報重復定義錯誤。

          強引用和弱引用

          除了強符號和弱符號的區(qū)別之外,GNUC還有一個特性就是強引用和弱引用,我們知道的是,編譯器在編譯階段只負責將源文件編譯成目標文件(即二進制文件),然后由鏈接器對所有二進制文件進行鏈接操作。

          在分離式編譯中,當編譯器檢查到當前使用的函數(shù)或者變量在本模塊中僅有聲明而沒有定義時,編譯器直接使用這個符號,將工作轉交給鏈接器,鏈接器則負責根據(jù)這些信息找到這些函數(shù)或者變量的實體地址。

          因為在程序執(zhí)行時,程序必須確切地知道每個函數(shù)和全局變量的地址。如果沒有找到該符號的實體,就會報undefined reference錯誤,這種符號之間的引用被稱為強引用.

          編譯器默認所有的變量和函數(shù)為強引用,同時編程者可以使用 __attribute__((weakref)) 來聲明一個函數(shù),注意這里是聲明而不是定義,既然是引用,那么就是使用其他模塊中定義的實體,對于函數(shù)而言,我們可以使用這樣的寫法:

          __attribute__((weakref)) void func(void);

          然后在函數(shù)中調(diào)用func(),如果func()沒有被定義,則func的值為0,如果func被定義,則調(diào)用相應func,在《程序員的自我修養(yǎng)》這本書中有介紹,它是這樣寫的:

          __attribute__((weakref)) void func(void);
          void main(void)
          {
              if(func) {func();}
          }

          但是在現(xiàn)代的編譯系統(tǒng)中,這種寫法卻是錯誤的,編譯雖然通過(有警告信息),但是卻不正確:

          warning: ‘weakref’ attribute should be accompanied with an ‘a(chǎn)lias’ attribute [-Wattributes]

          警告顯示:weakref需要伴隨著一個別名才能正常使用

          強/弱符號和強/弱引用的作用

          這種弱符號、弱引用的擴展機制在庫的實現(xiàn)中非常有用。我們在庫中可以使用弱符號和弱引用機制,這樣對于一個弱符號函數(shù)而言,用戶可以自定義擴展功能的函數(shù)來覆蓋這個弱符號函數(shù)。

          同時我們可以將某些擴展功能函數(shù)定義為弱引用,當用戶需要使用擴展功能時,就對其進行定義,鏈接到程序當中,如果用戶不進行定義,則鏈接也不會報錯,這使得庫的功能可以很方便地進行裁剪和組合。

          注意:C標準里根本沒有提到強、弱符號。這只是GCC這個實現(xiàn)定義的特性,在MS C編譯器里是不存在這個概念的。



          參考博客:

          https://www.cnblogs.com/downey-blog/p/10470674.html https://blog.csdn.net/astrotycoon/article/details/8008629

          鏈接:https://xiaoyege.blog.csdn.net/article/details/93674095

          僅供大家學習參考與知識傳播,版權歸原作者所有,如有侵權,麻煩聯(lián)系進行刪除,感謝~

          瀏覽 17
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品久久久久久久久午夜福利 | 色婷婷国产在线观看 | 日本乱伦福利 | 色点点点丁香五月天 | 天天日天天干天天拍 |