色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

探究Linux GNU C與ANSI C之間的區別

奈因PCB電路板設計 ? 來源:嵌入式Linux系統開發 ? 作者:嵌入式Linux系統開 ? 2021-07-26 16:54 ? 次閱讀

Linux 上可用的 C 編譯器是 GNU C 編譯器,它建立在自由軟件基金會的編程許可證的基礎上,因此可以自由發布。GNU C對標準C進行一系列擴展,以增強標準C的功能。

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

GNU C允許使用零長度數組,在定義變長對象的頭結構時,這個特性非常有用。例如:

struct var_data {

int len;

char data[0];

};

char data[0]僅僅意味著程序中通過var_data結構體實例的data[index]成員可以訪問len之后的第index個地址,它并 沒有為data[]數組分配內存,因此sizeof(struct var_data)=sizeof(int)。

假設struct var_data的數據域就保存在struct var_data緊接著的內存區域中,則通過如下代碼可以遍歷這些數據:

struct var_data s;

。。。

for (i = 0; i 《 s.len; i++)

printf(“%02x”, s.data[i]);

GNU C中也可以使用1個變量定義數組,例如如下代碼中定義的“double x[n]”:

int main (int argc, char *argv[])

{

int i, n = argc;

double x[n];

for (i = 0; i 《 n; i++)

x[i] = i;

return 0;

}

2.case范圍

GNU C支持case x…y這樣的語法,區間[x,y]中的數都會滿足這個case的條件,請看下面的代碼:

switch (ch) {

case ‘0’。。。 ‘9’: c -= ‘0’;

break;

case ‘a’。。。 ‘f’: c -= ‘a’ - 10;

break;

case ‘A’。。。 ‘F’: c -= ‘A’ - 10;

break;

}

代碼中的case‘0’。。。‘9’等價于標準C中的:

case ‘0’: case ‘1’: case ‘2’: case ‘3’: case ‘4’:

case ‘5’: case ‘6’: case ‘7’: case ‘8’: case ‘9’:

3.語句表達式

GNU C把包含在括號中的復合語句看成是一個表達式,稱為語句表達式,它可以出現在任何允許表達式的地 方。我們可以在語句表達式中使用原本只能在復合語句中使用的循環、局部變量等,例如:

#define min_t(type,x,y)

( { type _ _x =(x);type _ _y = (y); _ _x《_ _y _ _x: _ _y; })

int ia, ib, mini;

float fa, fb, minf;

mini = min_t(int, ia, ib);

minf = min_t(float, fa, fb);

因為重新定義了__xx和__y這兩個局部變量,所以用上述方式定義的宏將不會有副作用。在標準C中,對應的如 下宏則會產生副作用:

#define min(x,y) ((x) 《 (y) (x) : (y))

代碼min(++ia,++ib)會展開為((++ia)《(++ib)(++ia):(++ib)),傳入宏的“參數”增加兩次。

4.typeof關鍵字

typeof(x)語句可以獲得x的類型,因此,可以借助typeof重新定義min這個宏:

#define min(x,y) ({ const typeof(x) _x = (x);

const typeof(y) _y = (y);

(void) (&_x == &_y);

_x 《 _y _x : _y; })

我們不需要像min_t(type,x,y)那個宏那樣把type傳入,因為通過typeof(x)、typeof(y)可以獲得type。代 碼行(void)(&_x==&_y)的作用是檢查_x和_y的類型是否一致。

5.可變參數宏

標準C就支持可變參數函數,意味著函數的參數是不固定的,例如printf()函數的原型為:

int printf( const char *format [, argument]。。。 );

而在GNU C中,宏也可以接受可變數目的參數,例如:

#define pr_debug(fmt,arg.。。)

printk(fmt,##arg)

這里arg表示其余的參數,可以有零個或多個參數,這些參數以及參數之間的逗號構成arg的值,在宏擴展時替換 arg,如下列代碼:

pr_debug(“%s:%d”,filename,line)

會被擴展為:

printk(“%s:%d”, filename, line)

使用“##”是為了處理arg不代表任何參數的情況,這時候,前面的逗號就變得多余了。使用“##”之后,GNU C預 處理器會丟棄前面的逗號,這樣,下列代碼:

pr_debug(“success!

”)

會被正確地擴展為:

printk(“success!

”)

而不是:

printk(“success!

”,)

6.標號元素

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

指定數組索引的方法是在初始化值前添加“[INDEX]=”,當然也可以用“[FIRST.。.LAST]=”的形式指定一個范圍。例如,下面的代碼定義了一個數組,并把其中的所有元素賦值為0:

unsigned char data[MAX] = { [0 。。。 MAX-1] = 0 };

下面的代碼借助結構體成員名初始化結構體:

struct file_operations ext2_file_operations = {

llseek: generic_file_llseek,

read: generic_file_read,

write: generic_file_write,

ioctl: ext2_ioctl,

mmap: generic_file_mmap,

open: generic_file_open,

release: ext2_release_file,

fsync: ext2_sync_file,

};

但是,Linux 2.6推薦類似的代碼應該盡量采用標準C的方式:

struct file_operations ext2_file_operations = {

.llseek = generic_file_llseek,

.read = generic_file_read,

.write = generic_file_write,

.aio_read = generic_file_aio_read,

.aio_write = generic_file_aio_write,

.ioct = ext2_ioctl,

.mmap = generic_file_mmap,

.open = generic_file_open,

.release = ext2_release_file,

.fsync = ext2_sync_file,

.readv = generic_file_readv,

.writev = generic_file_writev,

.sendfile = generic_file_sendfile,

};

7.當前函數名

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

void example()

{

printf(“This is function:%s”, __FUNCTION__);

}

代碼中的__FUNCTION__意味著字符串“example”。C99已經支持__func__宏,因此建議在Linux編程中不再使用__FUNCTION__,而轉而使用__func__:

void example(void)

{

printf(“This is function:%s”, __func__);

}

8.特殊屬性聲明

GNU C允許聲明函數、變量和類型的特殊屬性,以便手動優化代碼和定制代碼檢查的方法。要指定一個聲明的 屬性,只需要在聲明后添加__attribute__((ATTRIBUTE))。其中ATTRIBUTE為屬性說明,如果存在多個屬 性,則以逗號分隔。GNU C支持noreturn、format、section、aligned、packed等十多個屬性。

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

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

format屬性也用于函數,表示該函數使用printf、scanf或strftime風格的參數,指定format屬性可以讓編譯器根據格 式串檢查參數類型。例如:

asmlinkage int printk(const char * fmt, 。。。) __attribute__ ((format (printf, 1, 2)));

上述代碼中的第1個參數是格式串,從第2個參數開始都會根據printf()函數的格式串規則檢查參數。

unused屬性作用于函數和變量,表示該函數或變量可能不會用到,這個屬性可以避免編譯器產生警告信息。

aligned屬性用于變量、結構體或聯合體,指定變量、結構體或聯合體的對齊方式,以字節為單位,例如:

struct example_struct {

char a;

int b;

long c;

} __attribute__((aligned(4)));

表示該結構類型的變量以4字節對齊。

packed屬性作用于變量和類型,用于變量或結構體成員時表示使用最小可能的對齊,用于枚舉、結構體或聯合體類型時表示該類型使用最小的內存。例如:

struct example_struct {

char a;

int b;

long c __attribute__((packed));

};

編譯器對結構體成員及變量對齊的目的是為了更快地訪問結構體成員及變量占據的內存。例如,對 于一個32位的整型變量,若以4字節方式存放(即低兩位地址為00),則CPU在一個總線周期內就可以讀取32 位;否則,CPU需要兩個總線周期才能讀取32位。

9.內建函數

GNU C提供了大量內建函數,其中大部分是標準C庫函數的GNU C編譯器內建版本,例如memcpy()等,它們與對應的標準C庫函數功能相同。

不屬于庫函數的其他內建函數的命名通常以__builtin開始,如下所示。

內建函數__builtin_return_address(LEVEL)返回當前函數或其調用者的返回地址,參數LEVEL指定調用棧的級數,如0表示當前函數的返回地址,1表示當前函數的調用者的返回地址。

內建函數__builtin_constant_p(EXP)用于判斷一個值是否為編譯時常數,如果參數EXP的值是常數,函數返回1,否則返回0。例如,下面的代碼可檢測第1個參數是否為編譯時常數以確定采用參數版本還是非參數版本:

#define test_bit(nr,addr)

(__builtin_constant_p(nr)

constant_test_bit((nr),(addr)) :

variable_test_bit((nr),(addr)))

內建函數__builtin_expect(EXP,C)用于為編譯器提供分支預測信息,其返回值是整數表達式EXP的值,C的 值必須是編譯時常數。

Linux內核編程時常用的likely()和unlikely()底層調用的likely_notrace()、unlikely_notrace()就是基于 __builtin_expect(EXP,C)實現的。

#define likely_notrace(x) __builtin_expect(!!(x), 1) #define unlikely_notrace(x) __builtin_expect(!!(x), 0)

若代碼中出現分支,則即可能中斷流水線,我們可以通過likely()和unlikely()暗示分支容易成立還是不容易 成立,例如:

if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev)))

if (ipv4_is_loopback(saddr))

goto e_inval;

在使用gcc編譯C程序的時候,如果使用“-ansi–pedantic”編譯選項,則會告訴編譯器不使用GNU擴展語法。例如對 于如下C程序test.c:

struct var_data {

int len;

char data[0];

};

struct var_data a;

直接編譯可以通過:

gcc -c test.c

如果使用“-ansi–pedantic”編譯選項,編譯會報警:

gcc -ansi -pedantic -c test.c

test.c:3: warning: ISO C forbids zero-size array ‘data’

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11292

    瀏覽量

    209330

原文標題:Linux GNU C 與 ANSI C 有什么區別?

文章出處:【微信號:pcbgood,微信公眾號:奈因PCB電路板設計】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    同樣是函數,在CC++中有什么區別

    同樣是函數,在 CC++ 中有什么區別? 第一個返回值。 C語言的函數可以不寫返回值類型,編譯器會默認為返回 int。 但是 C++
    的頭像 發表于 11-29 10:25 ?272次閱讀

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

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

    GNU構建裸機系統

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

    linux開發板和單片機開發的區別

    硬件架構 Linux開發板和單片機開發在硬件架構上有很大的區別Linux開發板通常基于ARM、x86或其他處理器架構,具有較高的處理能力和內存容量。而單片機開發則基于微控制器,如8051、AVR
    的頭像 發表于 08-30 15:30 ?732次閱讀

    PLC編程語言和C語言的區別

    在工業自動化和計算機編程領域中,PLC(可編程邏輯控制器)編程語言和C語言各自扮演著重要的角色。盡管兩者都是編程語言,但它們在多個方面存在顯著的區別。本文將從多個維度深入探討PLC編程語言和C語言的
    的頭像 發表于 06-14 17:11 ?2783次閱讀

    USB-C和TYPE-C有哪些區別

    USB-C和TYPE-C都是現代電子設備中常見的接口類型,它們在外觀和功能上具有一定的相似性,但也存在一些區別。本文將從多個方面對USB-C和TYPE-
    的頭像 發表于 04-03 15:33 ?5440次閱讀
    USB-<b class='flag-5'>C</b>和TYPE-<b class='flag-5'>C</b>有哪些<b class='flag-5'>區別</b>

    在STM32中,通信串口USART與I2C之間有啥原理上的區別?二者之間又有什么聯系?

    請問一下,在STM32中,通信串口USART與I2C之間有啥原理上的區別?二者之間又有什么聯系?對于所有的通信之間,又存在什么樣的關聯?
    發表于 03-25 07:27

    type-c和usb-c有什么區別

    type-c和usb-c有什么區別? Type-C 和 USB-C 都是指同一個連接標準,它使用統一的連接器,在電子設備
    的頭像 發表于 02-19 10:00 ?2615次閱讀

    c語言,c++,java,python區別

    C語言、C++、Java和Python是四種常見的編程語言,各有優點和特點。 C語言: C語言是一種面向過程的編程語言。它具有底層的特性,能夠對計算機硬件進行直接操作。
    的頭像 發表于 02-05 14:11 ?2366次閱讀

    vb語言和c++語言的區別

    VB語言和C++語言是兩種不同的編程語言,雖然它們都屬于高級編程語言,但在設計和用途上有很多區別。下面將詳細比較VB語言和C++語言的區別。 設計目標: VB語言(Visual Bas
    的頭像 發表于 02-01 10:20 ?2258次閱讀

    C++在Linux內核開發中從爭議到成熟

    Linux 內核郵件列表中一篇已有六年歷史的老帖近日再次引發激烈討論 —— 主題是建議將 Linux 內核的開發語言從 C 轉換為更現代的 C++。
    的頭像 發表于 01-31 14:11 ?623次閱讀
    <b class='flag-5'>C</b>++在<b class='flag-5'>Linux</b>內核開發中從爭議到成熟

    usb-c和type-c區別一樣嗎

    USB-C 和 Type-C 是同一種接口的兩種叫法,它們沒有區別。即 USB-C 和 Type-C 是同義詞,用來描述一種連接接口標準。
    的頭像 發表于 01-31 10:44 ?6288次閱讀

    賽昉系列:OK7110-C_Qt5.15.2+Linux5.15.0_編譯手冊_V1.0

    OK7110-C_Qt5.15.2+Linux5.15.0_編譯手冊_V1.0_20230820
    發表于 01-23 16:23 ?0次下載

    USB–C和type–C一樣嗎 type-c和usb-c有什么區別

    小巧、可逆插拔以及支持多種功能而得到了廣泛的應用。 USB-C連接器相較于傳統的USB連接器有以下幾個方面的區別: 外形設計:USB-C連接器的外形更加小巧,比傳統的Type-A和Type-B連接器要
    的頭像 發表于 01-18 09:52 ?9168次閱讀

    i2c接口和spi接口區別

    重要的區別。 I2C接口和SPI接口都屬于串行通信接口標準,廣泛應用在嵌入式系統和電子設備中。它們之間的主要區別在于通信協議、電氣特性、速度和適用場景等方面。 I2
    的頭像 發表于 12-25 15:02 ?3998次閱讀
    主站蜘蛛池模板: 成人国产在线24小时播放视频| 少妇的肉体AA片免费| gv手机在线观看| 人人澡人人擦人人免费| 囯产精品久久久久久久久免费蜜桃| 双腿打开揉弄高潮H苏安安秦慕深 双腿被绑成M型调教PLAY照片 | 国产在线精彩亚洲久久| 亚洲三级成人| 老师小扫货水能么多叫出来| caoporn免费视频在线| 十分钟免费视频大全在线观看| 国产午夜永久福利视频在线观看| 妖精视频在线观看高清| 蜜芽资源高清在线观看| 成年人视频免费在线播放| 无码137片内射在线影院| 国产色婷亚洲99精品AV在| 亚洲精品美女久久777777| 日本高清二区| china18一19 第一次| 色综合久久久久久| 精品水蜜桃久久久久久久| 97国产成人精品免费视频| 色戒2小时38分在线观看| 黑人巨茎vide抽搐| 51国产偷自视频在线视频播放| 日本无码人妻丰满熟妇5G影院| 国产亚洲精品久久精品6| 中文国产成人精品久久免费| 全部老头和老太XXXXX| 国产一区二区内射最近更新| 2020精品国产视| 色综合久久五月| 久久亚洲精品AV成人无| 成人麻豆日韩在无码视频| 亚洲免费观看在线视频| 男女无遮挡吃奶gift动态图| 国产精品AV视频一二三区| 在线播放一区二区精品产| 日本人HD18HD18| 久久99免费视频|