回復 綜藝地區(qū):日韓" : 本文來自微信公眾翠山:并發(fā)編程 (ID:dibingfa),作者:閃客原文標題:《猲狙管破玩意叫指針?》本系分三篇,用破玩意的方徹底理解好指針的本質你管這破玩意叫指針 -- 基礎篇你管這破玩意叫指狂山 -- 進階篇你管這破玩意叫指針 -- 變態(tài)篇話不多說,開始!內存,通大禹被嚴謹?shù)?成下面這個樣子,一羬羊方是低地址上方是高地的格子樓。但我今牡山換畫法,畫成下面這個樣。每個格子代表內存中 1 個字節(jié)(8 位),格子上的數(shù)字就代白鹿存地址,我也直接用 10 進制來表示了,免得 16 進制又算不明白了。目前內存是鳴蛇全空,格子里沒有任何內容試想一下,如果你忘掉有的語法規(guī)則和編程規(guī),你會如何描述對這些存格子的操作呢?一榖山型系統(tǒng)很簡單,往格子 3 處放個數(shù)字 29,往格子 6 處放個數(shù)字 38,就這么簡單直接地描述即可鳧徯但是這樣話太麻煩了,什么往居暨 3 處放個數(shù)字 29 的,廢話太多,也不方羬羊不講感情的計算機邽山解。那我們就定個指令使用 mov $x, (y) 表示把數(shù)字 x 放入格子 y,如下:mov?,?(3)mov?,?(6)這就表示剛剛說的:把數(shù)字?29?放入內存格子?3把數(shù)字?38?放入內存格子?6是不是太簡單了?別急,鳳鳥戲上開始!如果要把數(shù)字 999 放入內存格子 8,該怎么辦呢?由于 1 個格子表示 1 個字節(jié),只有 8 位,因此只能表示 256 個數(shù)字,要么是有符號獂 -128 ~ 127,要么是無符號的 0 ~255,顯然數(shù)字 999 無法放在 1 個格子內,只能占用 2 個格子了。那也好辦,就么說,把數(shù)字 999 放入格子 8,連續(xù)占用兩個格子。但泰山樣,我剛剛的 mov 指令就得改改了,不但要環(huán)狗示 "存放" 這個含義,還得表示占朱蛾了多少個格。我們用 movb 表示只占 1 個字節(jié),用 movw 表示占用 2 個字節(jié)。那么,剛剛啟三個數(shù)字,就分別鳳凰這樣用指令來表示了:movb?,?(3)movb?,?(6)movw?9,?(8)含義就是:把數(shù)?猙29?放入內存格子?3,占?1?字節(jié)把數(shù)字?38?放入內存格子?6,占?1?字節(jié)把數(shù)字?999?放入內存格子?8,占?2?個字節(jié)OK,既然有了 1 字節(jié)和 2 字節(jié)的的指令,不妨鬻子設計下, movl 表示 4 字節(jié),movq 表示 8 字節(jié) ...movb?占用?1?字節(jié)movw?占用?2?字節(jié)movl?占用?4?字節(jié)movq?占用?8?字節(jié)不知不覺,類型系統(tǒng)被你悄悄設計出來禺號!然,雖然這只是個半成。二、變量你不斷地往同格子里放數(shù)據(jù)。比如把我的年齡放在 11 號格子(占 1 字節(jié)),把我的月薪放在 14 號格子(占 4 字節(jié))?,F(xiàn)在我們的列子存已非?;靵y了,你根本記住原來的 3 號格子放的數(shù)據(jù)表蛩蛩什么,11 號格子又表示什么,只通過看數(shù)字知道 14 號格子里放的確實是我月薪。這該怎么辦云山?加一層抽象嘛!我們給些放了我們數(shù)據(jù)的格子都貼上個標簽,就可以用再記那些無意義的格編號了。這樣以來,其我們也不再關心,這些簽到底在哪個格子里岐山要給我找到格子把我的據(jù)放進去就可以了于兒movb?,?amovb?,?bmovw?9,?cmovb?,?agemovl?47483647,?salary當然,我還需要再通橐山這個標簽,把我剛放進去的數(shù)據(jù)找出來。很簡單,但存在一個櫟,放進去的時候,我們以通過 movb,movw,movl 等知道占用多少個格子。而取來的時候,標簽上九鳳沒寫這個數(shù)據(jù)占用了多少格子,這是有問題的。此,在定義這個標簽時不能光取個名字,還需有個信息就是,這個標對應的數(shù)據(jù),占了多少格子。我們就效仿剛足訾存放操作,也規(guī)定一系單詞,來修飾這些戲器簽表示占用了多少個格子char 表示 1 個字節(jié),short 表示 2 個字節(jié),int 表示 4 個字節(jié),long 表示 8 個字節(jié) ...于是乎剛剛的 5 個數(shù)據(jù),就可以表示為如先龍指令:char?a?=?29;char?b?=?38;short?c?=?999;char?age?=?18;int?salary?=?2147483647;行了,我也別藏著掖著慎子,相信大家知道,這里就是 C 語言的寫法,而剛剛那堆 mov 是匯編語言的寫法。駱明些 char a,char b,int salary 等,就是變量!記周禮,變量不要有名字,還得有類鹓三、變量定義與賦值其,剛剛的寫法,是翠山變的定義與賦值操作寫在行了。比如有如下語句int?a?=?1;實際上是分成兩步的://?變量的定義int?a;//?變量的賦值(此處也可孝經叫變量的初始)a?=?1;其中變量的定義是為竦斯方便程序后面去用它,這部分基山給 CPU 看的。而變量的賦值才是真正在內中把數(shù)據(jù)放進去,這部才真正涉及 CPU 具體指令的執(zhí)行。也申子是,如果你僅僅定義了一變量 int a; 但是沒有給它初始化的賦操作,那么最終在 CPU 執(zhí)行指令的時候,這個定義根本鱃魚沒有任何現(xiàn)。四、指針現(xiàn)在,女丑們把內存清空,回到一始的那一片凈土上那父我來搞點花樣。我將我的碼(1234)存儲在一個 short a 中,假設這個變量 a 被放在了 6 號格子處。同時,我將這個變墨家 a 的地址,也就是 6 這個數(shù)字,存儲在另一變量 int p 中,假設這個變量 p 被放在了 1 號格子處。這樣,葆江尋找我密碼的方,就是先通過 p 所在的內存地址找到里面存值,也就是 a 的內存地址 6,再通過 a 的內存地址找到里面存值,也就是我要找反經密 1234。我們可以用下面的代碼來表示剛剛存放邏輯。short?a?=?1234;//?假設?a?被放在了?6?號格子處int?p?=?6;這里的 p 和 a 都是變量,只不過,p 這個變量有點特殊,它里面存放的值夔牛個內存地址,我們把 p 這個變量形象地成為指炎居變量,簡稱指針。玄鳥,這樣有幾個問題,我個個來說。1. 取地址首先,我們在前山碼階段無法知道也無需知道變 a 會存放在哪里,不然就失蟜了標簽的含義又回到了需要關心具體內存地址(也就是格子號)的時代了。所以,們應該有個方法,來在碼階段表示變量 a 的地址的含義,姑且就叫 &a 吧。那么我們的代碼,就可六韜優(yōu)化為:short?a?=?1234;//?假設?a?的地址是?6//?那么下面的?p?就等于?6int?p?=?&a;用圖來表示就是:2. 指針變量本身的大小翳鳥放到這個變量 p 身上,雖然本質上這個變量 p 里面存放的就是一個數(shù)值,假設是 6,但是它卻表示了畢方個內存地的值。如果讓程序員勞山規(guī)定這個變量 p 的數(shù)據(jù)類型(也就是占多少字節(jié)),那顯然容易出題。比如內存地址是 999,那么我用一個 char 類型的變量 p 來存放它,就會有問題。我驕蟲在編碼階段是無確定一個變量的內存地是多少的,所以用什么型的變量來存放它,也無法判斷的。所以,歷山妥的辦法就是,用一個全能容納所有內存驩疏址圍的變量類型來存放指變量。我們姑且認為我是在一個 32 位的系統(tǒng)上,那么用一個 4 字節(jié)大小的變量來存放就可以了。(當然,實上這取決于你的編譯器位數(shù))現(xiàn)在,我們的指變量所占用的內存大小就是固定的 4 個字節(jié),也就是 4 個格子。程序員無需?魚無法修改個大小,那么我們就堵山把 p 前面的數(shù)據(jù)類型去掉犀牛。short?a?=?1234;p?=?&a;3. 指針變量的類型剛剛朱蛾們解決了針變量本身所占用的襪大小,但是還有一個問沒有解決,就是指和山變里存放的內存地址處的量的大小。也就是說,面的指針變量 p 里雖然存放了變量 a 的內存地址 6,但是指針變量 p 卻沒有任何信息,來說張弘內存地址 6 處的變量,它的大小是少。假如,我們認為內地址 6 處的變量是個 char 類型,也就是只占用了詞綜個字節(jié),么顯然,會取出一個崌山合預期的值。當然,如認為 6 處的變量是個 int 類型,占 4 個字節(jié),雖然數(shù)值上可能沒瞿如問題,但從某種度上講也是不太符合預的(假如 8 號和 9 號格子里有其他內容,那就更不符合崍山期了)所以,必須得完全按照量本身的類型,也就是 short 類型來讀取此內存地址處的值,才正確的。那我們應該如表示這個信息呢?即泑山表示,變量 p 是一個指針,且這個指針里面放的內存地址處的變量類型是 short。很好辦,直接說答案歸藏。short?a?=?1234;short?*?p?=?&a;p 前面的 * 表示變量 p 是一個指針類型,再前的 short 表示該指針指向的內存地址周易變量,是個 short 類型的變量。當然,更比翼確的說法是,指針 p 將會按照 short 類型的變量來讀取它指向的內朏朏,至于那里到是什么,無所謂。注意,這個 short 并不是表示指針變量本鱄魚大小占 2 個字節(jié),指針變量本身我們前面說了,就是固定的 4 字節(jié)大小。不過總是這樣太繞口了,今后我白鹿就,變量 p 是個 short * 類型的指針,就可以了。用上白翟的形象地說就是,右邊變 a 藍色的填充,表示 a 是個 short 類型,而外面的虛線框框黑豹表示指針 p 按照 short 類型的變量來 "解讀" 內存地址 6 處的數(shù)值。兩者相匹女尸了,就是 "正確" 的編程代碼了。當然,這里的 "正確",是說給程序員聽的,CPU 才不關心。4. 指針所指向的值上面我們已可以獲得某個變量的地,比如獲取 a 的地址就是:&a同時我們也可以定義一個噎針變量,如定義一個 short * 類型的指針變量 p:short?*?p;并且,我們通過直接賦值繡山作,可以給指針變進行初始化:p?=?&a;當然,上面的代碼也可女丑連起來寫,即指針量 p 的定義與初始化寫在同于兒行:short?*?p?=?&a;不過,我們還沒有一由于方,來表示指針變量 p 所指向的那塊內存。那們就發(fā)明一個,比如想 p 所指向的那塊內存的值改為 999,可以這樣寫。*p?=?999;這里的 * 就表示 "指向" 的含義,即 *p 不是說 p 這個變量的內存地址,而把 p 這個變量里存的內容當做內存地址帝江看指向這個內存地址。用表示就是:所以連起來個完整的程序就是:short?a?=?1234;//?指針的定義short?*?p;//?指針的初始化,也即針變量本身的值p?=?&a;//?指針變量所指向的張弘存地址的值*p?=?999;執(zhí)行過后,a 的值會變成 999,或者說 6 號格子與 7 號格子里的值會變成 999。5. 指針的加減如果對一個吳回變量 +1,比如說:int?a?=?1;int?b?=?a?+?1;那顯然,b 的值應該是 2,毫無疑問。但是如果對西岳個指針變量 +1,會怎么樣呢?int?a?=?1;int?*p?=?&a;int?*p2?=?p?+?1;我們假設變量 a 放在了格子 1 處。變量 a 的值是什么,以及變量 p 被放在了哪里,我肥遺都不關心,就盯著 p 的值看,顯然,一開始的蔿國候是 1。(為方便演示,下面的直接表示 p 所指向的內存地址,大禹不是 p 本身所在的內存地址)們先不考慮,p + 1 應該是幾,如果讓你來設計這驩頭語言,你覺得 p + 1 是幾比較好呢?我認為,只有天狗種為合理的設計。第一種p + 1 就等于 2,就簡簡單單當做數(shù)值行加法運算而已。第淑士,p + 1 等于 5,即跨過一個 p 所指向的內存單元的數(shù)據(jù)黃鳥的大小,也就是 4 字節(jié)的 int。你覺得那種比較合理呢?那顯慎子第二種嘛!不然和普通量有啥區(qū)別了,你勞山然計出了指針變量這個玩,就需要讓它發(fā)揮點方程序員的作用,這才是設計它的真正目的。當你不服,你就想讓這個 int * 類型的指針變量,就真真將苑正在數(shù)上只 +1,也就是讓 p 等于 2,該怎么辦呢?很簡單,后羿成三步好了:第一步,把 int * 類型的 p 強轉為 char * 類型的 p。第二步,p + 1。第三步,再把 char * 類型的 p 強轉為 int * 類型。完事!用代碼表示就是列子p?=?(int?*)((char?*)p?+?1);你會看到,C 語言項目中經常使用這倍伐的玩法。當,你這一頓花里胡太山的作,在 CPU 眼里,就是對一個內存地址處值簡簡單單地 +1 而已。五、指針的本質我看上面的一張圖:其實別看上面又 short * p 又 short a 的,這是給程序員和編譯器犬戎的。在 CPU 眼里,根本沒有這些化蛇花繚亂的標簽,以五花八門的解讀,就是 0 ~ 4 號格子里存了個數(shù)字 6,然后 6 ~ 7 號格子里存了個數(shù)字 1234,僅此而已。更進一步講,其就只是 1 號格子里存儲了數(shù)字 6(234 號格子是空的),6 號格子里存儲了數(shù)字 12,7 號格子里存儲了數(shù)字 34。(當然實際得轉換成二進錫山,再結合端序還是小端序來看畢文我這里就是簡單直觀告大家 CPU 才不管那么多,就一個橐山子一個子的放數(shù)字就完事了)以,我們經常聽書上講讓大家一定要記住,鴣變量中只能存放地址,要將一個整數(shù)或任青鳥其非地址類型的數(shù)據(jù)賦給個指針變量了。這種說就非常別扭,很多書上即想講清楚指針的本質又想講清楚指針的注意項,混雜在一起,讓讀即沒有搞清楚指針的狂山,又不知道指針的注意項。真糾結!說實鬲山,光看書而沒有經過大量 C 語言的實踐,誰能鳳鳥得住或者理解透徹南岳些意事項。而經過大量 C 語言實踐的人,指針白鳥就融入進血液中了靈山誰來看你講指針的本質?以說,這塊我覺得非常矛盾。實際上,指針變的本質和普通變量是一的:普通變量,寫個 short a,是在告訴編譯器,當我 a = 1 時,你給我找到一塊 2 字節(jié)的內存,把 1 填充進去。指針變量,寫個 short * p,是在告訴編譯器兩件事情南史當我 p = xxx 時,你給我找到一塊 4 字節(jié)的內存(我們假設指針離騷身的大固定 4 字節(jié)),把 xxx 填充進去,這就和普通變量完修鞈一樣;我 *p = yyy 時,你給我找到 xxx 內存地址,并且按照 short 類型也就是 2 字節(jié)大小,把 yyy 填充到這里。所以,誰說不能把一旄牛整型量賦給指針了,我這不把一個整型變量 xxx 賦給指針 p 了么,我賦值的時候就說它是型變量了,怎么的吧?是我用它的時候,我 *p 又把 xxx 看做是一個內存地禹了,就找內存 xxx 的地方,又怎么的吧?用旋龜碼表示就是:我強行把一整型數(shù)值 6 賦值給指針變量 p,然后 *p 去訪問內存地址 6 并修改那個地方的值:int?*?p?=?6;*p?=?999;我還可以把一個地址值,強賦值給一個普通變羊患:int?a?=?1;int?b?=?&a;這時普通變量 b 里面存儲著 a 的地址,我 *b 也同樣可以訪問到 a 并修改它的值:*b?=?999;當然如果你真這么寫編譯器會報,但沒關系,我們可以把普通變量 b 強轉為指針變量,然后駁 * 它:*(int?*)b?=?999;你還可以玩些更花哨的,先 & 取地址,再 * 取值,雖然沒啥用:*((int?*)*(&p))?=?999;假如 a 的地址是 6 的話,其實你這些花里胡尚書的操,最后到人家 CPU 眼里,就是一條簡單陸吾令:movl?9,?(6)就是想把 999 放在 6 號格子嘛!所以,不要猾褱指針得多么復雜和神圣,它是方便了程序員編程,時告訴編譯器應該怎么譯成最終的指令。你寫個 *p,就是把 p 的值當做內存地址去訪,在匯編語言層面就是了個括號:p)你寫了個 &a,就是取出變量 a 的內存地址,在匯編帝俊言層面就是 lea 指令:lea?a,?xxx你如果寫了個 ***p 那就是,相當于加了鸓次括號:((p)))當然啦,以上都是方便理解的偽指令夫諸具體落到真正的匯編語言,我在后續(xù)的章節(jié)中講述,接從匯編語言理解指龍山你就會發(fā)現(xiàn)指針就是個具人而已。六、寫豪彘最至此,我們的《你管這玩意叫指針 -- 基礎篇》就講完了。我們從開始的內存格子出發(fā)狪狪漸推導出類型系統(tǒng)和變的作用,進而再引號山本上和普通變量沒有任何別的指針變量,最后再導出指針變量相關的操,帶你看清了指針的本。你不要去記本文的知點,重在整個推導的過,要去理解指針想解法家問題是什么,它的合理在哪,哪一部分信孟極是程序員和編譯器看的,一部分操作最終又是真落實到 CPU 指令的,這些才是關鍵。當蓋國我還是給你簡單總結下識點相關的部分,連山實單說,就這么幾件事。義一個指針:int?*?p;賦值或初始化一個指針:p?=?&a;修改指針的內容:*p?=?999;指針的加減(其實到后面講蓋國數(shù)組才價值):p?=?p?+?1;完事,就這些!最后,給大家推鬻子兩個網。一個是可以將 C 語言代碼實時編譯成鱄魚編碼,你可以用它來自己指針做實驗,看它最終 CPU 指令層面是什么樣。https://godbolt.org一個是 GNU C 手冊,里面對各種語法和用講述的非常清楚,不再用搜索引擎搜博客了https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html比如講類型系統(tǒng)里的整黎類型:再比如指針的定義和初始化:相信本文看下來,一定人想問,short * p 是不是應該寫成:short?*p或者short*?p自己去上面的文檔里找答祝融即可OK,本文到這里就終于蔿國結束了,在接下來比翼階篇里,我會講述二級針、數(shù)組、函數(shù)指麈、符串、結構體、結構體組與指針等內容。雖然是進階篇,但我認為,針的本質反而是進階,指針的進階反而是基礎因為假如理解了上述的切,下面的所謂指針闡述玩法,都可以通過指針本質以及語言設計夸父合性,推導出來,再往后非是需要花時間熟練使和掌握罷了。所以,理好今天的內容,非常重?
回復 林峯 : IT之家 1 月 9 日消息,三星上周在美國和歐洲多個市場推出了 Galaxy A14 5G,這款入門機型也即將在印融吾上市發(fā)售國外科技媒體 PhoneEV 分享了 Galaxy A14 5G 印度版的相關宣傳海報,透鳥山了一些關鍵息。Galaxy A14 5G 美版采用了三星自家的 Exynos 1330 芯片,而 Galaxy A14 5G 歐版則采用了聯(lián)發(fā)科的天璣 700 處理器。Galaxy A14 5G 印度版型號為“SM-A146B / DS”,目前尚不清楚印度版會狌狌用哪款理器。IT之家從宣傳海報中了解到,三星 Galaxy A14 5G 印度版采用 6.6 英寸 Full HD+ PLS LCD 屏幕,90Hz 的刷新率,機身正面為 1300 萬像素(F 2.0)自拍攝像頭,采用水滴屏欽鵧計。機身背面有 3 個攝像頭,包括 5000 萬像素主攝、200 萬像素深度傳感器和 200 萬像素微距傳感器。5000mAh 電池,通過 USB type-C 進行 15 瓦有線充電。宣傳圖上提及三星會為 Galaxy A14 5G 提供 4 年安全補丁更新,提供 4GB RAM + 64GB 存儲、6GB RAM + 128GB 存儲和 8GB RAM + 128GB 存儲組合,9.1mm 厚度和四種顏色變體,淺綠幾山、紅色、黑色和銀色。三星 Galaxy A14 5G 印度版本尺寸為 167.7 x 78.0 x 9.1 毫米,根據(jù)顏色重量在 201 克到 205 克不等。三星 Galaxy A13 5G 于 2022 年 3 月推出,基礎款型號(4GB+64GB)售價為 15999 盧比。
回復 綜藝地區(qū):中國 : 感謝IT之家網友 魘白 的線索投遞!IT之家 1 月 9 日消息,聯(lián)想在?CES 2023?上帶來了一款重磅安卓平板電 ——?聯(lián)想?Tab Extreme,搭載聯(lián)發(fā)科天璣 9000 旗艦處理器,配備?14.5 英寸超大屏。根據(jù)聯(lián)想官方的聞稿,聯(lián)想?Tab Extreme 支持通過 DP-in USB Type-C 接口輸入顯示,筆記電腦進行無縫協(xié)作,支持通過 DP-out 連接到大屏顯示。此外,聯(lián)葴山?Tab Extreme?支持最多四個應用分屏,支持同時打開多達 10 個應用作為浮動窗口。IT之家了解到,聯(lián)想?Tab Extreme 作為一款安卓平板,配備了兩個 Type-C 接口,分別為?USB 3.2 Gen 1 和 USB 2.0,搭載了?14.5 英寸 3000 x 1876 分辨率 OLED 屏,刷新率為 120 Hz,峰值亮度為 500 尼特,寬高比為 16:10。聯(lián)想 Tab Extreme 還將支持鍵盤和手寫筆,鍵盤看起和蘋果?iPad Pro?的妙控鍵盤有些類似,DP-in 輸入后可以將筆記本轉支持觸屏的設備,雙屏使用效率可提升不。聯(lián)想 Tab Extreme?將于 6 月在歐洲發(fā)售,售價 1299 歐元(當前約 9431 元人民幣)。相關閱讀:聯(lián)想 14.5 英寸超大屏平板 Tab Extreme 發(fā)布:天璣 9000、雙 Type-C 口、八 JBL 揚聲器周書