在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

3天內不再提示

C語言語法擴展

汽車電子技術 ? 來源:宅學部落 ? 作者: 王利濤 ? 2023-02-17 09:34 ? 次閱讀

Linux 內核驅動中的奇怪語法

大家在看一些 GNU 開源軟件,或者閱讀 Linux 內核、驅動源碼時會發現,在 Linux 內核源碼中,有大量的 C 程序看起來“怪怪的”。說它是C語言吧,貌似又跟教材中的寫法不太一樣;說它不是 C 語言呢,但是這些程序確確實實是在一個 C 文件中。此時,你肯定懷疑你看到的是一個“假的 C 語言”!

比如,下面的宏定義:

#define mult_frac(x, numer, denom)({\\
typeof(x) quot = (x) / (denom);\\        
typeof(x) rem  = (x) % (denom);\\
(quot * (numer)) + ((rem * (numer)) / (denom));\\
})
#define ftrace_vprintk(fmt, vargs)\\
do {\\    
if (__builtin_constant_p(fmt)) {\\        
static const char *trace_printk_fmt __used \\
  __attribute__((section("__trace_printk_fmt"))) = \\
  __builtin_constant_p(fmt) ? fmt : NULL; \\
  __ftrace_vbprintk(_THIS_IP_, trace_printk_fmt, vargs);\\
  } 
else \\
  __ftrace_vprintk(_THIS_IP_, fmt, vargs);\\
} while (0)

字符驅動的填充:

static const struct 
file_operations 
lowpan_control_fops = {
.open =lowpan_control_open,
.read = seq_read,
.write=lowpan_control_write,
 .llseek = seq_lseek,
 .release = single_release,
 };

內核中實現打印功能的宏定義:

#define pr_info(fmt, ...)\\
__pr(__pr_info, fmt, ##__VA_ARGS__)

#define pr_debug(fmt, ...)\\
__pr(__pr_debug, fmt, ##__VA_ARGS__)

你沒有看錯,這些其實也是 C 語言,但并不是標準的 C 語言語法,而是我們 Linux 內核使用的 GNU C 編譯器擴展的一些 C 語言語法。這些語法在 C 語言教材或資料中一般不會提及,所以你才會似曾相識而又感到陌生,看起來感覺“怪怪的”。我們在做 Linux 驅動開發,或者閱讀 Linux 內核源碼過程中,會經常遇到這些“稀奇古怪”的用法,如果不去了解這些特殊語法的具體含義,可能就對代碼的理解造成一定障礙。

本文和接下來的幾篇文章,將帶領大家一起去了解 Linux 內核或者 GNU 開源軟件中,常用的一些 C 語言特殊語法擴展,掃除閱讀 Linux 內核或 GNU 開源軟件時,這些擴展特性帶給我們的語法閱讀障礙和困惑。

C 語言標準和編譯器

在進入正式學習之前,先給大家普及一下 C 標準的概念。在學習 C 語言時,大家在教材或資料上,或多或少可能見到過“ANSI C”的字眼。可能當時沒有太在意,其實“ANSI C” 表示的就是 C 語言標準。

什么是 C 語言標準呢?我們生活的現實世界,就是由各種標準構成的,正是這些標準,我們的社會才會有條不紊的運行。比如我們過馬路,遵循的交通規則就是一個標準:紅燈停,綠燈行,黃燈亮了等一等。當行人和司機都遵循這個默認的標準時,我們的交通系統才會順暢運行。電腦中的 USB 接口也是一種標準,當大家生產的 USB 產品都遵循 USB 協議這種通信標準時,我們的手機、U 盤、USB 攝像頭、USB 網卡才可以在各種電腦設備上互插互拔。2G、3G、4G 也是一種標準,當不同廠家生產的基帶芯片都遵循這種通信標準,我們所用的不同品牌、不同操作系統的手機才可能互相打電話、互相發微信、互相給對方點贊。

同樣,C 語言也有它自己的標準。我們知道,C 語言程序需要通過編譯器,編譯生成二進制指令,才能在我們的電腦上運行。在 C 語言剛發布的早期,各大編譯器廠商開發自己的編譯器時,各自開發,各自維護,時間久了,就會變得比較混亂。這就會造成這樣一種局面:程序員寫的程序,在一個編譯器上編譯通過,在另一個編譯器編譯通不過。大家按各自的習慣來,誰也不服誰,就像春秋戰國時代:不同的貨幣、不同的度量衡,不同的文字,都是中國人,因為標準不統一,所以交流起來很麻煩,這樣下去也不是辦法啊。

后來 ANSI(AMERICAN NATIONAL STANDARDS INSTITUTE: 美國國家標準協會,簡稱 ANSI)出山了,聯合 ISO(國際化標準組織)召集各個編譯器廠商大佬,各種技術團體,一起喝個茶、開個碰頭會,開始啟動 C 語言的標準化工作。期間各種大佬之間也是矛盾重重,充滿各種爭議,但功夫不負有心人,經過艱難的磋商,終于在1989年達成一致,發布了 C 語言標準,后來第二年又做了一些改進。于是,就像秦始皇統一六國、統一文字和度量衡一樣,C 語言標準終于問世了!因為是在 1989 年發布的,所以人們一般稱其為 C89 或 C90 標準,或者叫做 ANSI C。

C 標準內容

C 標準里主要講了什么?

C 標準英文文檔,洋洋灑灑幾百頁,講了很多東西,但總體歸納起來,主要就是 C 語言編程的一些語法慣例,比如:

  • 定義各種關鍵字、數據類型
  • 定義各種運算規則
  • 各種運算符的優先級和結合性
  • 數據類型轉換
  • 變量的作用域
  • 函數原型
  • 函數嵌套層數
  • 函數參數個數限制
  • 標準庫函數

C 標準發布后,大家都遵守這個標準:程序員開發程序時,按照這種標準寫;編譯器廠商開發編譯器時,也按照這種標準去解析、翻譯程序。不同的編譯器廠商支持統一的標準,這樣大家寫的程序,使用不同的編譯器,都可以正確編譯、運行,大大提高程序的開發效率,推動了 IT 行業的發展。

C 標準的發展過程

C 標準并不是永遠不變的,就跟移動通信一樣,也是從 2G、3G、4G 到 5G 不斷發展變化的。C 標準也經歷了下面四個階段:

  • K&R C
  • ANSI C
  • C99
  • C11

K&R C

K&R C 一般也稱為傳統 C。在 C 標準沒有統一之前,C 語言的作者 Dennis Ritchie 和 Brian Kernighan 合作寫了一本書《C 程序設計語言》。早期程序員編程,這本書可以說是絕對權威。這本書很薄,內容精煉,主要介紹了 C 語言的基本使用方法。后來《C 程序設計語言》第二版問世,做了一些修改:比如新增 unsigned int、long int、struct 等數據類型;把運算符 =+/=- 修改為 +=/-=,避免運算符帶來的一些歧義和 Bug。這本書可以看作是 ANSI 標準的雛形。但早期的 C 語言還是很簡單的,比如還沒有定義標準庫函數、沒有預處理命令等。

ANSI C

ANSI C 是 ANSI(美國國家標準協會)在 K&R C 的基礎上,統一了各大編譯器廠商的不同標準,并對 C 語言語法和特性做了一些擴展,而發布的一個標準。這個標準一般也叫做 C89/C90,也是目前各種編譯器默認支持的 C 語言標準。ANSI C 主要新增了以下特性:

  • 增加 signed、volatile、const 關鍵字
  • 增加 void* 數據類型
  • 增加預處理器命令
  • 增加寬字符、寬字符串
  • 定義了 C 標準庫
  • ……

C99 標準

C99 標準是 ANSI 1999 年在 C89 標準的基礎上新發布的一個標準,該標準對 ANSI C 標準做了一些擴充,比如新增一些關鍵字,支持新的數據類型:

  • 布爾型:_Bool
  • 復數:_Complex
  • 虛數:_Imaginary
  • 內聯:inline
  • 指針修飾符:restrict
  • 支持long long、long double數據類型
  • 支持變長數組
  • 允許對結構體特定成員賦值
  • 支持16進制浮點數、float _Complex等數據類型
  • ……

除此之外,C99 標準也借鑒其它語言的一些優點,對語法和函數做了一系列改進,大大方便了程序員開發程序,比如:

  • 變量聲明可以放代碼塊的任何地方。ANSI C 規定變量的聲明要全部寫在函數語句的最前面,否則就會報編譯錯誤?,F在不需要這樣寫了,哪里需要使用變量,在哪里直接聲明使用即可;
  • 源程序每行最大支持4095個字節。這個貌似足夠用了,沒有什么程序能復雜到一行程序有4KB個字符;
  • 支持//單行注釋。ANSI C使用/**/沒有C++的//注釋方便,所以 C99 新標準借鑒過來了,也開始支持這種注釋方式;
  • 標準庫新增了一些頭文件:如 stdbool.h、complex.h、stdarg.h、fenv.h 等。大家在 C 語言中經常返回的 true、false,其實這也是 C++ 里面定義的 bool 類型。那為什么我們經常這樣寫,而編器編譯程序時沒有報錯呢,這是因為早期大家編程使用的都是 VC++6.0 系列,是 C++ 編譯器。還有一種可能就是有些 IDE 對這個數據類型的數據做了封裝。

C11 新標準

C11 標準是2011年發布的最新 C 語言標準,修改了 C 語言標準的一些 Bug、新增了一些特性:

  • 增加 _Noreturn,聲明函數無返回值;
  • 增加_Generic:支持泛型編程;
  • 修改了標準庫函數的一些 Bug:如 gets( )函數被 gets_s() 函數代替;
  • 新增文件鎖功能;
  • 支持多線程;
  • ……

從 C11 標準的修改內容來看,也慢慢察覺到 C 語言未來的發展趨勢:C 語言現在也在借鑒現在編程語言的優點,不斷添加到自己的標準里面。比如現代編程語言的多線程、字符串、泛型編程等,C 語言最新的標準都支持。但是這樣下去,C 語言是不是還能保持她“簡單就是美”的優雅特色呢,我們只能慢慢期待了。但至少目前我們不用擔心這些,因為 C11 新發布的標準,目前絕大多數編譯器還不支持,所以我們暫時還用不到。

編譯器對 C 標準的支持

標準是一回事,各種編譯器支不支持是另一回事,這一點,大家要搞清楚。這就跟手機一樣,不同時期發布的手機對通信標準支持也不一樣。早期的手機可能只支持 2G 通信,后來支持 3G,現在發布的新款手機基本上都支持 4G了,而且可以兼容 2G/3G。

現在 5G 標準正在研發,快發布了,據說 2019 年發布,2020 年商用。但是目前還沒有手機支持 5G 通信,就跟現在沒有編譯器支持 C11 標準一樣。

不同編譯器,甚至對 C 標準的支持也不一樣。有的編譯器只支持 ANSI C,這是目前默認的 C 標準。有的編譯器可以支持 C99,或者支持 C99 標準的部分特性。目前對 C99 標準支持最好的是 GNU C 編譯器,據說可以支持 C99標準99%的新增特性。

編譯器對 C 標準的擴展

不同編譯器,出于開發環境、硬件平臺、性能優化的需要,除了支持 C 標準外,還會自己做一些擴展。

51單片機上用 C 語言開發程序,我們經常使用 Keil for C51 集成開發環境。你會發現 Keil for C51 或其他 IDE 里的 C 編譯器會對 C 語言標準作很多擴展。比如增加各種關鍵字:

  • data:RAM 的低128B空間,單周期直接尋址;
  • code:表示程序存儲區;
  • bit:位變量,常用來定義單片機的 P0~P3 管腳;
  • sbit:特殊功能位變量;
  • sfr:特殊功能寄存器
  • reentrant:重入函數聲明。

如果你在程序中使用以上這些關鍵字,那么你的程序就只能使用51編譯器來編譯運行,你使用其它的編譯器,比如 VC++6.0,是編譯通不過的。

同樣的道理,GCC 編譯器,也對 C 標準做了很多擴展:

  • 零長度數組
  • 語句表達式
  • 內建函數
  • __attribute__特殊屬性聲明
  • 標號元素
  • case 范圍
  • ...

比如支持零長度數組。這些新增的特性,C 標準目前是不支持的,其它編譯器也不支持。如果你在程序中定義一個零長度數組:

int a[0];

只能使用 GCC 編譯器才能正確編譯,使用 VC++ 6.0編譯器編譯可能就通不過,因為微軟的 C++ 編譯器不支持這個特性。

教程主要內容

本文是《C語言嵌入式Linux高級編程》第5期:Linux內核中GNU C語法擴展視頻教程的文本預覽版,如果想系統學習一下C語言標準及Linux內核中的GNU C擴展語法,可以到51CTO學院或CSDN學院搜索講師名字:“王利濤”,即可觀看相關教程?;蛘咴诎俣戎校苯铀阉鳌巴趵麧币部梢哉业较嚓P視頻教程。

在 GNU 開源軟件、Linux 內核中會大量使用 GCC 自己擴展的語法,這會對我們理解開源軟件、Linux 內核代碼帶來一定障礙和困擾。本教程主要介紹 GNU C 對 C 標準擴展的一些常用語法和使用。終極目標是看懂 Linux 內核驅動、GNU 開源軟件中這些特殊語法的應用,掃除這些特殊語法對我們理解內核代碼帶來的困擾和障礙。

本教程需要的學習環境

在本教程講解中,會使用一些 arm-linux-gnueabi-gcc 等命令用來編譯和反匯編程序。所以在學習本教程之前,確保你的電腦上有如下 Linux 環境或源代碼:

  • Linux學習環境:Ubuntu、Fedora等皆可;
  • arm-linux-gnueabi-gcc 交叉編譯工具;
  • Linux 內核源碼:Linux 4.4.x
  • U-boot-2016.09 源代碼
備注

本教程是《C語言嵌入式Linux高級編程》第5期:Linux內核中的GNU C語法擴展,文本預覽版,如果想系統學習Linux內核中的各種GNU C擴展及使用技巧,可百度搜索:“王利濤”,到51CTO學院或CSDN學院點擊相關課程即可開始系統學習。

如果您手頭暫時沒有 Linux 學習環境,也可以在 Windows 環境下安裝 C-Free 學習。教程中的 C 語言示例程序在 C-Free 環境下面也能編譯通過。當然在這里,還是建議您使用虛擬機安裝一個 Linux 學習環境,一個良好的環境更有利于我們的學習,在安裝過程有什么疑惑,可以通過郵件(3284757626@qq.com)聯系,也可以加入QQ群(475504428),參與技術討論。

微信公眾號:宅學部落

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

    關注

    180

    文章

    7618

    瀏覽量

    138709
  • LINUX內核
    +關注

    關注

    1

    文章

    316

    瀏覽量

    21867
  • GNU
    GNU
    +關注

    關注

    0

    文章

    143

    瀏覽量

    17598
收藏 人收藏

    評論

    相關推薦

    C語言相關資料(編程規范,語法解析等等)

    眼不說,隔一段時間再看的時候實在是費很大氣力;有一些基礎的C語言語法,或許你看過郭天祥的51那本書之后就沒有再深究過了,不是說郭天祥大哥寫的書不好,而是或許那些知識入門綽綽有余,但是我們有必要深究常用C
    發表于 12-23 17:19

    請問下面的C語言語句表達什么意思?

    下面的C語言語句表達什么意思??
    發表于 11-01 04:14

    C語言語句的規則函數

    的,而C語言語句的規則函數返回的數據類型+函數名+參數+函數主體所以這幾行代碼也就不難理解了。該函數類型是void型,函數名稱是Delay,_IO是類型修飾符,指的是單片機的靜態IO口;uint_32_t是指32位的無符號整形變量;由for循環構成了函數的主體,意思是32
    發表于 07-14 08:13

    Linux內核中GNU C擴展的一些常用C語言語法分析

    13.1 總結前面12節的課程,主要針對 Linux 內核中 GNU C 擴展的一些常用 C 語言語法進行了分析。GNU C 的這些
    發表于 12-14 06:29

    Linux內核中的C語言語法擴展

    收集一些感覺比較好的博客鏈接,方便以后再看Linux 內核中的 C 語言語法擴展Linux 內核驅動中的指定初始化宏構造利器:語句表達式Linux 內核第一宏:container_of零長
    發表于 12-15 06:04

    YACC在ATLAS語言語法分析中的沖突消解研究

    對使用YACC工具進行ATLAS語言語法分析過程中出現的大量沖突進行了詳細的分類討論與研究,給出了實現過程中出現的主要沖突類型及相應解決方案:文法符號的不斷自身循環產生
    發表于 09-08 15:30 ?0次下載

    C語言語法基礎

    發表于 07-06 15:18 ?7次下載

    C語言誤用易錯知識點與基本語法匯總

    語言之所以能稱之為語言,它肯定是一種工具一種相互交流相互通信相互傳達之間的意圖的工具,作為語言那肯定得有自己的語法,要想相互交流肯定得先學好它的語法
    發表于 05-05 15:32 ?2106次閱讀

    Prel語法C語言語法的異同綜述

    Prel語法C語言語法的異同綜述
    發表于 05-25 11:44 ?6次下載

    嵌入式系統常用的C語言基本語法概要

    嵌入式系統常用的C語言基本語法概要
    發表于 10-20 12:51 ?6次下載
    嵌入式系統常用的<b class='flag-5'>C</b><b class='flag-5'>語言</b>基本<b class='flag-5'>語法</b>概要

    單片機中常用的C語言語句合集

    單片機中常用的C語言語句合集
    發表于 01-12 09:24 ?45次下載

    C語言有哪些語法技巧和功能

    C語言常常讓人覺得它所能表達的東西非常有限。它不具有類似第一級函數和模式匹配這樣的高級功能。但是C非常簡單,并且仍然有一些非常有用的語法技巧和功能,只是沒有多少人知道罷了。
    的頭像 發表于 03-10 17:42 ?2119次閱讀

    第九章 AVR C語言的應用.PDF

    本教程講解的是AVR C語言編程,包括開發環境、語言語法、特殊用法基礎知識的講解
    發表于 03-17 14:21 ?0次下載

    C語言_語句與位運算基本練習

    總結C語言語句的幾個基本練習題,計算素數、排序、求偶數和、可逆素數、水仙花數、交換大小寫、交換變量的值、位運算、語法特性等知識點。
    的頭像 發表于 08-14 09:46 ?1143次閱讀

    初學C語言不了解的那些事~

    其實C語言語法非常簡單,可以說是目前主流編程語言語法點最少的一門編程語言了,然而C
    發表于 08-07 10:00 ?306次閱讀
    主站蜘蛛池模板: 在线看片成人免费视频 | 六月丁香六月婷婷 | 4438成人成人高清视频 | 国产不卡毛片 | 在线观看www日本免费网站 | 99久久精品免费看国产免费 | 色婷亚洲| 成人亚洲欧美 | 天天爽夜夜爽天天做夜夜做 | 日本三级欧美三级香港黄 | 亚洲亚洲人成网站在线观看 | 8050网午夜一级毛片免费不卡 | 精品在线一区二区三区 | 99 久久99久久精品免观看 | 国产色婷婷精品免费视频 | 女人午夜啪啪性刺激免费看 | 久久狠狠第一麻豆婷婷天天 | 国产美女久久久久 | 偷拍福利视频 | 免费不卡毛片 | 亚洲卡5卡6卡7国色天香 | 亚洲 欧美 日韩 丝袜 另类 | 久久精品福利 | 9久久9久久精品 | 国产98色在线 | 免费人成网站永久 | 欧洲不卡一卡2卡三卡4卡网站 | 中文字幕一区二区三区永久 | 七月色婷婷 | 手机看片福利盒子久久青 | 久久奇米 | 综合黄色| 亚洲福利视频一区二区 | 欧美在线一区二区三区 | 亚洲狠狠狠一区二区三区 | 黄色午夜剧场 | 午夜精品久久久久久毛片 | 欧美伊人网| 黄色靠逼网站 | 2017av在线 | 丁香婷婷开心激情深爱五月 |