那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

C語言開發中可能會用到的GNU

Q4MP_gh_c472c21 ? 來源:開源博客 ? 作者:-_-struggle ? 2021-11-17 10:41 ? 次閱讀

為了方便使用,GNU C在標準C語言的基礎上進行了部分方便開發的擴展。

這里講解一些開發中可能會用到的,或者使用頻率比較高的內容。

零長度數組和變量長度數組

GNU C 允許使用零長度數組,比如:

char data[0];

GNU C 允許使用一個變量定義數組的長度如:

int n=0;
scanf("%d",&n);
int array[n];

case 范圍

GNU C支持 case x...y這樣的語法,[x,y]之間數均滿足條件。

case 'a'...'z':  /*from 'a' to 'z'*/
break;

語句表達式


GNU C 把包含在括號中的復合語句看作是一個表達式,稱為語句表達式。

 #define min_t(type,x,y)
         ({type __x=(x); type __y=(y);__x<__y?__x:__y;})

這種寫法可以避免:

 #define min_t(x,y) ((x)<(y)?(x):(y))

在min_t(x++,++y)中出現的副作用。

typeof 關鍵字

typeof(x)可以獲得x的類型借助typeof關鍵字我們可以重新定義min_t:

#define min_t(x,y)
    ({typeof(x) __x=(x); typeof(y) __y=(y);__x<__y?__x:__y;})

可變參數宏

GNU C中宏也支持可變參數:

#define pr_debug(fmt,arg...) 
        printk(fmt,##arg)

這里,如果可變參數被忽略或為空,“##”操作將使預處理器去掉它前面的那個逗號。如果你在宏調用時,確實提供了一些可變參數,GNU C也會工作正常,它會把這些可變參數放到逗號的后面。

標號元素

標準C要求數組或結構體的初始化值必須以固定的順序出現,在GNU C中,通過指定索引或結構體成員名,允許初始化以任意順序出現。

unsigned char data[MAX] =
{
         [0]=10,
         [10]=100,
};


struct file_operations ext2_file_operations=
{
        open:ext2_open,
        close:ext2_close,
};

linux 2.6中推薦如下方式:

struct file_operations ext2_file_operations=
{
     .read=ext2_read,
     .write=ext2_write,
};

當前函數名

GNU C中預定義兩個標志符保存當前函數的名字,__ FUNCTION __ 保存函數在源碼中的名字, __ PRETTY__ FUNCTION __保存帶語言特色的名字。在C函數中這兩個名字是相同的。

void func_example()
{
     printf("the function name is %s",__FUNCTION__);
}

在C99中支持__ func __ 宏,因此建議使用 __ func __ 替代 __ FUNCTION __ 。

特殊屬性聲明

GNU C 允許聲明函數、變量和類型的特殊屬性,以便進行手工的代碼優化和定制。如果要指定一個屬性聲明,只需要在聲明后添加__ attribute __((ATTRIBUTE))。其中ATTRIBUTE為屬性說明,如果存在多個屬性,則以逗號分隔。GNU C 支持noreturn,noinline, always_inline, pure, const, nothrow, format, format_arg, no_instrument_function, section, constructor, destructor, used, unused, deprecated, weak, malloc, alias warn_unused_result nonnull等十個屬性。

noreturn屬性作用于函數,表示該函數從不返回。這會讓編譯器優化代碼并消除不必要的警告信息。例如:

#define ATTRIB_NORET __attribute__((noreturn)) ....
asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;

packed屬性作用于變量和類型,用于變量或結構域時,表示使用最小可能的對齊,用于枚舉、結構或聯合類型時表示該類型使用最小的內存。如對于結構體,就是它告訴編譯器取消結構在編譯過程中的優化對齊,按照實際占用字節數進行對齊。例如:

struct example_struct
{
         char a;
         int b;
         long c;
} __attribute__((packed));

regparm屬性用于指定最多可以使用n個寄存器(eax, edx, ecx)傳遞參數,n的范圍是0~3,超過n時則將參數壓入棧中(n=0表示不用寄存器傳遞參數)。

注意:以上這些屬性都是在X86處理器體系結構下的,在X64體系結構下,大部分內容都是同樣有效的。但是,這里要注意regparm屬性,由于在X64體系結構下,GUN C的默認調用約定使用寄存器傳遞參數。所以,如果regparm屬性里使用的寄存器個數超過3個,也仍然會使用其他寄存器來傳遞參數。這一點要遵循X64體系結構的調用約定。

下面可以看一個例子:

int q = 0x5a;
int t1 = 1;
int t2 = 2;
int t3 = 3;
int t4 = 4;
#define REGPARM3 __attribute((regparm(3)))
#define REGPARM0 __attribute((regparm(0)))
void REGPARM0 p1(int a)
{
     q = a + 1;
}


void REGPARM3 p2(int a, int b, int c, int d)
{
     q = a + b + c + d + 1;
}


int main()
{
    p1(t1);
    p2(t1,t2,t3,t4);
    return 0;
}

使用objdump命令反匯編,相關命令如下:

objdump -D 可執行程序

其中-D選項用于反匯編所有的程序段,包括:代碼段、數據段、只讀數據段以及一些系統段等等。而-d命令只反匯編代碼段的內容。

反匯編后的關鍵代碼如下:

Disassembly of section .text:
0000000000400474 :
  400474:    55                       push   %rbp
  400475:    48 89 e5                 mov    %rsp,%rbp
  400478:    89 7d fc                 mov    %edi,-0x4(%rbp)
  40047b:    8b 45 fc                 mov    -0x4(%rbp),%eax
  40047e:    83 c0 01                 add    $0x1,%eax
  400481:    89 05 3d 04 20 00        mov    %eax,0x20043d(%rip)        # 6008c4 
  400487:    c9                       leaveq 
  400488:    c3                       retq   


0000000000400489 :
  400489:    55                       push   %rbp
  40048a:    48 89 e5                 mov    %rsp,%rbp
  40048d:    89 7d fc                 mov    %edi,-0x4(%rbp)
  400490:    89 75 f8                 mov    %esi,-0x8(%rbp)
  400493:    89 55 f4                 mov    %edx,-0xc(%rbp)
  400496:    89 4d f0                 mov    %ecx,-0x10(%rbp)
  400499:    8b 45 f8                 mov    -0x8(%rbp),%eax
  40049c:    8b 55 fc                 mov    -0x4(%rbp),%edx
  40049f:    8d 04 02                 lea    (%rdx,%rax,1),%eax
  4004a2:    03 45 f4                 add    -0xc(%rbp),%eax
  4004a5:    03 45 f0                 add    -0x10(%rbp),%eax
  4004a8:    83 c0 01                 add    $0x1,%eax
  4004ab:    89 05 13 04 20 00        mov    %eax,0x200413(%rip)        # 6008c4 
  4004b1:    c9                       leaveq 
  4004b2:    c3                       retq   


00000000004004b3 
: 4004b3: 55 push %rbp 4004b4: 48 89 e5 mov %rsp,%rbp 4004b7: 53 push %rbx 4004b8: 8b 05 0a 04 20 00 mov 0x20040a(%rip),%eax # 6008c8 4004be: 89 c7 mov %eax,%edi 4004c0: e8 af ff ff ff callq 400474 4004c5: 8b 0d 09 04 20 00 mov 0x200409(%rip),%ecx # 6008d4 4004cb: 8b 15 ff 03 20 00 mov 0x2003ff(%rip),%edx # 6008d0 4004d1: 8b 1d f5 03 20 00 mov 0x2003f5(%rip),%ebx # 6008cc 4004d7: 8b 05 eb 03 20 00 mov 0x2003eb(%rip),%eax # 6008c8 4004dd: 89 de mov %ebx,%esi 4004df: 89 c7 mov %eax,%edi 4004e1: e8 a3 ff ff ff callq 400489 4004e6: b8 00 00 00 00 mov $0x0,%eax 4004eb: 5b pop %rbx 4004ec: c9 leaveq 4004ed: c3 retq 4004ee: 90 nop 4004ef: 90 nop Disassembly of section .data: 00000000006008c0 <__data_start>: 6008c0: 00 00 add %al,(%rax) ... 00000000006008c4 : 6008c4: 5a pop %rdx 6008c5: 00 00 add %al,(%rax) ... 00000000006008c8 : 6008c8: 01 00 add %eax,(%rax) ... 00000000006008cc : 6008cc: 02 00 add (%rax),%al ... 00000000006008d0 : 6008d0: 03 00 add (%rax),%eax ... 00000000006008d4 : 6008d4: 04 00 add $0x0,%al ...

如果讀者還記得2.2.3節中,關于GCC基于X64體系結構的調用約定的話,那就很容易可以看出,函數p1和p2都使用寄存器傳遞參數,順序就是RDI, RSI, RDX, RCX,這些細節已經跟regparm的規定完全不一致了。所以,在這里作者覺得,regparm已經不起作用了。

來源:https://my.oschina.net/LinuxDaxingxing/blog/751319
責任編輯:haq
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C語言
    +關注

    關注

    180

    文章

    7614

    瀏覽量

    137720
  • GNU
    GNU
    +關注

    關注

    0

    文章

    143

    瀏覽量

    17542

原文標題:你知道GNU C對C語言的擴展嗎?

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    語言模型開發語言是什么

    在人工智能領域,大語言模型(Large Language Models, LLMs)背后,離不開高效的開發語言和工具的支持。下面,AI部落小編為您介紹大語言模型
    的頭像 發表于 12-04 11:44 ?231次閱讀

    MCU編程語言開發環境介紹

    微控制器單元(Microcontroller Unit,簡稱MCU)是嵌入式系統的核心,廣泛應用于各種電子產品。隨著技術的發展,MCU編程語言開發環境也在不斷進步,以適應不同的應用需求。 1.
    的頭像 發表于 11-01 11:51 ?1073次閱讀

    C語言C++結構體的區別

    同樣是結構體,看看在C語言C++中有什么區別?
    的頭像 發表于 10-30 15:11 ?356次閱讀

    C語言與其他編程語言的比較

    C語言作為一種歷史悠久的編程語言,自其誕生以來,一直在軟件開發領域扮演著重要角色。它以其高效、靈活和可移植性強的特點,成為了系統級編程的首選語言
    的頭像 發表于 10-29 17:30 ?368次閱讀

    GNU構建裸機系統

    基于AT91SAM7S平臺,介紹裸機開發,以閃燈為藍本,涉及匯編、鏈接、C/C++、中斷等。   無處不在的ARM處理器家族得到了GNU C
    發表于 10-16 17:34 ?0次下載

    求助,關于D類功放的幾個問題求解

    大于20kHz的頻率(最高可能會用到70,80k),我看到幾款功放的手冊寫到帶寬可以高達80kHz,不知實際應用可以實現這么高頻率的輸出嗎? 2、如果可以實現的話能否推薦一下對應的型號或者產品?
    發表于 10-15 06:38

    hex文件如何查看原c語言代碼

    直接將 .hex 文件轉換回原始的 C 語言代碼是不可能的,因為 .hex 文件是二進制文件,它包含了單片機程序編譯后的機器碼,這些機器碼與原始的 C
    的頭像 發表于 09-02 10:37 ?2795次閱讀

    請問ESP-AT在編譯過程中會用到哪些源文件?

    如題,請問ESP-AT在編譯過程中會用到哪些源文件?要修改藍牙相關的代碼應該修該哪些呢?有通透的大神指點一下嗎?謝謝!
    發表于 06-27 06:59

    c語言怎么做可視化界面

    C語言是一種通用的編程語言,廣泛應用于系統編程、嵌入式開發等領域。雖然C語言本身并不支持直接創建
    的頭像 發表于 06-06 10:46 ?2567次閱讀

    上位機軟件開發用什么語言

    維護的上位機軟件至關重要。本文將詳細介紹幾種常用的上位機軟件開發編程語言,并分析它們的優缺點。 C/C++ C
    的頭像 發表于 06-06 10:44 ?2261次閱讀

    GNU make中文手冊

    電子發燒友網站提供《GNU make中文手冊.pdf》資料免費下載
    發表于 06-05 13:22 ?0次下載

    嵌入式C語言結構體基本實現

    C語言中的數組只能允許程序員定義存儲相同類型數據。但是結構是C語言編程中允許您存儲不同數據類型的數據。 結構體的定義 ????要想定義結構,必須用到
    的頭像 發表于 05-11 08:49 ?1129次閱讀
    嵌入式<b class='flag-5'>中</b><b class='flag-5'>C</b><b class='flag-5'>語言</b>結構體基本實現

    C語言:嵌入式開發的關鍵編譯器角色

    嵌入式程序開發跟硬件密切相關,需要使用C語言來讀寫底層寄存器、存取數據、控制硬件等,C語言和硬件之間由編譯器來聯系,一些
    發表于 04-26 14:53 ?697次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>:嵌入式<b class='flag-5'>開發</b><b class='flag-5'>中</b>的關鍵編譯器角色

    幫你避雷 C語言所謂的短路現象~

    C語言短路現象算是C語言的基礎吧,不過有時候代碼寫得不規范也容易引入一些bug,所以這些操作在工程師實踐盡量少用。雖然下面找的例子比較簡單
    的頭像 發表于 03-27 08:09 ?451次閱讀
    幫你避雷 <b class='flag-5'>C</b><b class='flag-5'>語言</b>所謂的短路現象~

    cyusb3014枚舉的工作原理是什么?如果下載固件后不枚舉,可能會是什么原因,原理是什么?

    我用3014設計自己的板子,參考開發板kit3的原理圖,插入計算機后可以被識別為Bootloader,采用USB啟動模式,下載實例的固件后,顯示燒寫成功,但設備在計算機消失了,不再重新被枚舉。我
    發表于 02-29 07:11
    大发888官方 df888| 香港六合彩网址大全| 海王星娱乐网| 百家乐官网是如何骗人的| 总统百家乐官网的玩法技巧和规则 | 百家乐官网怎么玩啊| 丽景湾百家乐官网的玩法技巧和规则 | 渝北区| 百家乐官网必赢术| 百家乐破解仪恒达| 新竹市| 最好百家乐官网的玩法技巧和规则| 百家乐长龙技巧| 博彩通评价| 百家乐官网职业赌徒的解密| 网络百家乐诈骗| 大西洋娱乐城| 网上的百家乐官网是真是假| 哪个百家乐投注平台信誉好| 大发888娱乐开户| 百家乐官网庄家赢钱方法| 赌百家乐咋赢对方| 波克棋牌游戏大厅| 百家乐官网预约| 百家乐真人游戏娱乐| 水果机下载| 百家乐官网澳门色子| 大中华百家乐的玩法技巧和规则| 真钱百家乐官网送钱| 大世界百家乐娱乐城| 太阳城网络博彩| 阿玛尼百家乐官网的玩法技巧和规则| 全讯网xb112| 百盛百家乐官网软件| 百家百家乐官网网站| 百家乐官网真人荷官| 澳门百家乐先赢后输| 南溪县| 百家乐庄闲当哪个好| 澳门赌场色情| 百家乐比赛技巧|