0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語(yǔ)言開發(fā)中可能會(huì)用到的GNU

Q4MP_gh_c472c21 ? 來(lái)源:開源博客 ? 作者:-_-struggle ? 2021-11-17 10:41 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

為了方便使用,GNU C在標(biāo)準(zhǔn)C語(yǔ)言的基礎(chǔ)上進(jìn)行了部分方便開發(fā)的擴(kuò)展。

這里講解一些開發(fā)中可能會(huì)用到的,或者使用頻率比較高的內(nèi)容。

零長(zhǎng)度數(shù)組和變量長(zhǎng)度數(shù)組

GNU C 允許使用零長(zhǎng)度數(shù)組,比如:

char data[0];

GNU C 允許使用一個(gè)變量定義數(shù)組的長(zhǎng)度如:

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

case 范圍

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

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

語(yǔ)句表達(dá)式


GNU C 把包含在括號(hào)中的復(fù)合語(yǔ)句看作是一個(gè)表達(dá)式,稱為語(yǔ)句表達(dá)式。

 #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)中出現(xiàn)的副作用。

typeof 關(guān)鍵字

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

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

可變參數(shù)宏

GNU C中宏也支持可變參數(shù):

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

這里,如果可變參數(shù)被忽略或?yàn)榭?,?#”操作將使預(yù)處理器去掉它前面的那個(gè)逗號(hào)。如果你在宏調(diào)用時(shí),確實(shí)提供了一些可變參數(shù),GNU C也會(huì)工作正常,它會(huì)把這些可變參數(shù)放到逗號(hào)的后面。

標(biāo)號(hào)元素

標(biāo)準(zhǔn)C要求數(shù)組或結(jié)構(gòu)體的初始化值必須以固定的順序出現(xiàn),在GNU C中,通過(guò)指定索引或結(jié)構(gòu)體成員名,允許初始化以任意順序出現(xiàn)。

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,
};

當(dāng)前函數(shù)名

GNU C中預(yù)定義兩個(gè)標(biāo)志符保存當(dāng)前函數(shù)的名字,__ FUNCTION __ 保存函數(shù)在源碼中的名字, __ PRETTY__ FUNCTION __保存帶語(yǔ)言特色的名字。在C函數(shù)中這兩個(gè)名字是相同的。

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

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

特殊屬性聲明

GNU C 允許聲明函數(shù)、變量和類型的特殊屬性,以便進(jìn)行手工的代碼優(yōu)化和定制。如果要指定一個(gè)屬性聲明,只需要在聲明后添加__ attribute __((ATTRIBUTE))。其中ATTRIBUTE為屬性說(shuō)明,如果存在多個(gè)屬性,則以逗號(hào)分隔。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等十個(gè)屬性。

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

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

packed屬性作用于變量和類型,用于變量或結(jié)構(gòu)域時(shí),表示使用最小可能的對(duì)齊,用于枚舉、結(jié)構(gòu)或聯(lián)合類型時(shí)表示該類型使用最小的內(nèi)存。如對(duì)于結(jié)構(gòu)體,就是它告訴編譯器取消結(jié)構(gòu)在編譯過(guò)程中的優(yōu)化對(duì)齊,按照實(shí)際占用字節(jié)數(shù)進(jìn)行對(duì)齊。例如:

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

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

注意:以上這些屬性都是在X86處理器體系結(jié)構(gòu)下的,在X64體系結(jié)構(gòu)下,大部分內(nèi)容都是同樣有效的。但是,這里要注意regparm屬性,由于在X64體系結(jié)構(gòu)下,GUN C的默認(rèn)調(diào)用約定使用寄存器傳遞參數(shù)。所以,如果regparm屬性里使用的寄存器個(gè)數(shù)超過(guò)3個(gè),也仍然會(huì)使用其他寄存器來(lái)傳遞參數(shù)。這一點(diǎn)要遵循X64體系結(jié)構(gòu)的調(diào)用約定。

下面可以看一個(gè)例子:

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命令反匯編,相關(guān)命令如下:

objdump -D 可執(zhí)行程序

其中-D選項(xiàng)用于反匯編所有的程序段,包括:代碼段、數(shù)據(jù)段、只讀數(shù)據(jù)段以及一些系統(tǒng)段等等。而-d命令只反匯編代碼段的內(nèi)容。

反匯編后的關(guān)鍵代碼如下:

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節(jié)中,關(guān)于GCC基于X64體系結(jié)構(gòu)的調(diào)用約定的話,那就很容易可以看出,函數(shù)p1和p2都使用寄存器傳遞參數(shù),順序就是RDI, RSI, RDX, RCX,這些細(xì)節(jié)已經(jīng)跟regparm的規(guī)定完全不一致了。所以,在這里作者覺(jué)得,regparm已經(jīng)不起作用了。

來(lái)源:https://my.oschina.net/LinuxDaxingxing/blog/751319
責(zé)任編輯:haq
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7631

    瀏覽量

    141385
  • GNU
    GNU
    +關(guān)注

    關(guān)注

    0

    文章

    143

    瀏覽量

    17855

原文標(biāo)題:你知道GNU C對(duì)C語(yǔ)言的擴(kuò)展嗎?

文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 0人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    工業(yè)RTU會(huì)用到哪些芯片

    工業(yè)RTU(遠(yuǎn)程終端單元)通常會(huì)用到處理器芯片、通信芯片、數(shù)據(jù)采集芯片、存儲(chǔ)芯片和電源管理芯片等。
    的頭像 發(fā)表于 07-05 09:15 ?128次閱讀

    工業(yè)網(wǎng)關(guān)會(huì)用到哪些芯片

    工業(yè)網(wǎng)關(guān)通常會(huì)集成多種芯片以滿足其復(fù)雜的功能需求,具體可能會(huì)用到以下幾類芯片: 處理器芯片:這是工業(yè)網(wǎng)關(guān)的核心部件,負(fù)責(zé)執(zhí)行控制指令、數(shù)據(jù)處理以及運(yùn)行操作系統(tǒng)等任務(wù)。可能會(huì)采用高性能的ARM架構(gòu)
    的頭像 發(fā)表于 07-03 17:26 ?160次閱讀

    提高篇——C語(yǔ)言核心技術(shù)(中文版)

    嚴(yán)謹(jǐn)?shù)男g(shù)語(yǔ)表介紹C語(yǔ)言;第二部分描述標(biāo)準(zhǔn)鏈接庫(kù);第三部分介紹GNU軟件包中常用的編譯和測(cè)試工具。 獲取完整文檔資料可下載附件哦?。。?!如果內(nèi)容有幫助可以關(guān)注、點(diǎn)贊、評(píng)論支持一下哦~
    發(fā)表于 06-13 16:39

    HTTP協(xié)議在工業(yè)領(lǐng)域會(huì)用到

    HTTP協(xié)議在工業(yè)領(lǐng)域會(huì)用到,并且在工業(yè)互聯(lián)網(wǎng)、設(shè)備管理、數(shù)據(jù)交互等多個(gè)方面發(fā)揮著重要作用,以下為你詳細(xì)介紹: 工業(yè)互聯(lián)網(wǎng)場(chǎng)景 設(shè)備接入與管理 原理:在工業(yè)互聯(lián)網(wǎng)平臺(tái)中,各類工業(yè)設(shè)備(如傳感器
    的頭像 發(fā)表于 06-03 09:17 ?180次閱讀

    深入理解C語(yǔ)言C語(yǔ)言循環(huán)控制

    C語(yǔ)言編程,循環(huán)結(jié)構(gòu)是至關(guān)重要的,它可以讓程序重復(fù)執(zhí)行特定的代碼塊,從而提高編程效率。然而,為了避免程序進(jìn)入無(wú)限循環(huán),C語(yǔ)言提供了多種循
    的頭像 發(fā)表于 04-29 18:49 ?1087次閱讀
    深入理解<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>:<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>循環(huán)控制

    S32G2如何利用C語(yǔ)言開發(fā)IPCF?

    S32G2 應(yīng)該如何利用 C語(yǔ)言在 A 核上開發(fā) IPCF 程序,是否有相關(guān)的 SDK 可用?或者我需要將 ipc-shm 等封裝到一個(gè) C 庫(kù)
    發(fā)表于 03-27 06:49

    語(yǔ)言模型開發(fā)語(yǔ)言是什么

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

    ARM開發(fā)板編程語(yǔ)言選擇

    隨著物聯(lián)網(wǎng)(IoT)和智能設(shè)備的發(fā)展,ARM開發(fā)板因其低功耗、高性能和靈活性而受到開發(fā)者的青睞。 C語(yǔ)言 C
    的頭像 發(fā)表于 11-05 11:14 ?925次閱讀

    MCU編程語(yǔ)言開發(fā)環(huán)境介紹

    微控制器單元(Microcontroller Unit,簡(jiǎn)稱MCU)是嵌入式系統(tǒng)的核心,廣泛應(yīng)用于各種電子產(chǎn)品。隨著技術(shù)的發(fā)展,MCU編程語(yǔ)言開發(fā)環(huán)境也在不斷進(jìn)步,以適應(yīng)不同的應(yīng)用需求。 1.
    的頭像 發(fā)表于 11-01 11:51 ?2158次閱讀

    C語(yǔ)言C++結(jié)構(gòu)體的區(qū)別

    同樣是結(jié)構(gòu)體,看看在C語(yǔ)言C++中有什么區(qū)別?
    的頭像 發(fā)表于 10-30 15:11 ?746次閱讀

    C語(yǔ)言與Java語(yǔ)言的對(duì)比

    C語(yǔ)言和Java語(yǔ)言都是當(dāng)前編程領(lǐng)域中的重要成員,它們各自具有獨(dú)特的優(yōu)勢(shì)和特點(diǎn),適用于不同的應(yīng)用場(chǎng)景。以下將從語(yǔ)法特性、內(nèi)存管理、跨平臺(tái)性、性能、應(yīng)用領(lǐng)域等多個(gè)方面對(duì)C
    的頭像 發(fā)表于 10-29 17:31 ?1046次閱讀

    C語(yǔ)言與其他編程語(yǔ)言的比較

    C語(yǔ)言作為一種歷史悠久的編程語(yǔ)言,自其誕生以來(lái),一直在軟件開發(fā)領(lǐng)域扮演著重要角色。它以其高效、靈活和可移植性強(qiáng)的特點(diǎn),成為了系統(tǒng)級(jí)編程的首選語(yǔ)言
    的頭像 發(fā)表于 10-29 17:30 ?1052次閱讀

    GNU構(gòu)建裸機(jī)系統(tǒng)

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

    求助,關(guān)于D類功放的幾個(gè)問(wèn)題求解

    大于20kHz的頻率(最高可能會(huì)用到70,80k),我看到幾款功放的手冊(cè)寫到帶寬可以高達(dá)80kHz,不知實(shí)際應(yīng)用可以實(shí)現(xiàn)這么高頻率的輸出嗎? 2、如果可以實(shí)現(xiàn)的話能否推薦一下對(duì)應(yīng)的型號(hào)或者產(chǎn)品?
    發(fā)表于 10-15 06:38

    hex文件如何查看原c語(yǔ)言代碼

    直接將 .hex 文件轉(zhuǎn)換回原始的 C 語(yǔ)言代碼是不可能的,因?yàn)?.hex 文件是二進(jìn)制文件,它包含了單片機(jī)程序編譯后的機(jī)器碼,這些機(jī)器碼與原始的 C
    的頭像 發(fā)表于 09-02 10:37 ?4843次閱讀

    電子發(fā)燒友

    中國(guó)電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品