成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C語言內(nèi)存地址基礎(chǔ)

開發(fā) 后端
從計(jì)算機(jī)內(nèi)存的角度思考C語言中的一切東東,是挺有幫助的。我們可以把計(jì)算機(jī)內(nèi)存想象成一個(gè)字節(jié)數(shù)組,內(nèi)存中每一個(gè)地址表示 1 字節(jié)。

從計(jì)算機(jī)內(nèi)存的角度思考C語言中的一切東東,是挺有幫助的。我們可以把計(jì)算機(jī)內(nèi)存想象成一個(gè)字節(jié)數(shù)組,內(nèi)存中每一個(gè)地址表示 1 字節(jié)。比方說我們的電腦有 4K 內(nèi)存,那這個(gè)內(nèi)存數(shù)組將會有 4096 個(gè)元素。當(dāng)我們談?wù)撘粋€(gè)存儲地址的指針時(shí),就當(dāng)相于我們在談?wù)撘粋€(gè)存儲著該內(nèi)存數(shù)組某個(gè)元素索引的指針。逆向引用某個(gè)指針,將會得到數(shù)組中該索引所指向的 值。這一切當(dāng)然都是謊言。操作系統(tǒng)對內(nèi)存的管理要遠(yuǎn)比這復(fù)雜。內(nèi)存不一定連續(xù),也不一定按順序處理。但前面的類比是一種討論C語言內(nèi)存的簡單方式。

如果對『指針』、『地址』和『逆向引用』感到混亂,請看《C語言指針5分鐘教程》。// 譯注:“dereferencing” 的譯法比較多,本文采用了“逆向引用”。 

假設(shè)我們的計(jì)算機(jī)有 4K 的內(nèi)存,下一個(gè)開放地址的索引是2048。我們聲明一個(gè)新的字符變量i='a'。當(dāng)該變量所 獲得的內(nèi)存放置了它的值,變量的名字也與內(nèi)存中的該位置關(guān)聯(lián),我們的字符i就獲得了一個(gè)存儲在2048位置的值。該字符是單字節(jié)的因此它只占用了索引為 2048 的位置。如果我們對 i 變量使用地址操作符(&),它將返回到索引為2048的位置。如果這個(gè)變量是另一種類型,比如是 int,它將占用4字節(jié),在數(shù)組中占用索引為 2048-2051 的位置。使用地址操作符仍將返回索引2048的位置,因?yàn)?int 型即便占用了 4 字節(jié),但它開始于 2048 位置。我們看一個(gè)例子:

  1. // intialize a char variable, print its address and the next address  
  2. char charvar = '\0';  
  3. printf("address of charvar = %p\n", (void *)(&charvar));  
  4. printf("address of charvar - 1 = %p\n", (void *)(&charvar - 1));  
  5. printf("address of charvar + 1 = %p\n", (void *)(&charvar + 1));  
  6.    
  7. // intialize an int variable, print its address and the next address  
  8. int intvar = 1;  
  9. printf("address of intvar = %p\n", (void *)(&intvar));  
  10. printf("address of intvar - 1 = %p\n", (void *)(&intvar - 1));  
  11. printf("address of intvar + 1 = %p\n", (void *)(&intvar + 1));  

運(yùn)行將得到如下的輸出:

  1. address of charvar = 0x7fff9575c05f 
  2. address of charvar - 1 = 0x7fff9575c05e 
  3. address of charvar + 1 = 0x7fff9575c060 
  4. address of intvar = 0x7fff9575c058 
  5. address of intvar - 1 = 0x7fff9575c054 
  6. address of intvar + 1 = 0x7fff9575c05c 

在第一個(gè)例子的1-5行中,我們聲明了一個(gè)字符變量,并打印輸出該字符的地址,然后打印了內(nèi)存中位于該變量前后的兩個(gè)地址。我們是通過使 用&操作符并+1或-1來獲取前后兩個(gè)地址的。在7-11行的第二個(gè)例子中我們做了差不多的事,除了聲明了一個(gè)int型變量,打印出它的地址以及 緊鄰它前后的地址。

在輸出中,我們看到地址是 16 進(jìn)制的。更值得注意的是,字符的地址前后相差1字節(jié)。int 型變量地址前后相差四字節(jié)。內(nèi)存地址的算法、指針的算法、都是根據(jù)所引用的類型的大小的。一個(gè)給定的類型的大小是依賴于平臺的,我們這個(gè)例子中的char 是1字節(jié),int是四字節(jié)。將字符的地址-1是改地址前的地址,而將int型地址-1是該地址前4個(gè)的地址。

在例子中,我們是用地址操作符來獲取變量的地址,這和使用表示變量地址的指針是一樣的效果。

英文原博中評論已經(jīng)提出:存儲&charvar-1(一個(gè)非法的地址因它位于數(shù)組之前)在技術(shù)上是未特別指出的行為。C的標(biāo)準(zhǔn)已經(jīng)聲明,未特別指出的以及在一些平臺存儲一個(gè)非法地址都將引起錯(cuò)誤。

數(shù)組地址

在C語言中,數(shù)組是相鄰的內(nèi)存區(qū)域,它存儲了大量相同數(shù)據(jù)類型的值(int、long、*char等等)。很多程序員第一次用C時(shí),會將數(shù)組當(dāng)做指針。那是不對的。指針存儲一個(gè)簡單的內(nèi)存地址,而一個(gè)數(shù)組是一塊存儲多個(gè)值的連續(xù)的內(nèi)存區(qū)域。

  1. // initialize an array of ints 
  2. int numbers[5] = {1,2,3,4,5}; 
  3. int i = 0; 
  4.   
  5. // print the address of the array variable 
  6. printf("numbers = %p\n", numbers); 
  7.   
  8. // print addresses of each array index 
  9. do { 
  10.     printf("numbers[%u] = %p\n", i, (void *)(&numbers[i])); 
  11.     i++; 
  12. while(i < 5); 
  13.   
  14. // print the size of the array 
  15. printf("sizeof(numbers) = %lu\n"sizeof(numbers)); 

運(yùn)行將得到如下的輸出:

  1. numbers = 0x7fff0815c0e0 
  2. numbers[0] = 0x7fff0815c0e0 
  3. numbers[1] = 0x7fff0815c0e4 
  4. numbers[2] = 0x7fff0815c0e8 
  5. numbers[3] = 0x7fff0815c0ec 
  6. numbers[4] = 0x7fff0815c0f0 
  7. sizeof(numbers) = 20 

在這個(gè)例子中,我們初始化了一個(gè)含有 5 個(gè) int 元素的數(shù)組,我們打印了數(shù)組本身的地址,注意我們沒有使用地址操作符 & 。這是因?yàn)閿?shù)組變量已經(jīng)代表了數(shù)組首元素的地址。你會看到數(shù)組的地址與數(shù)組首元素的地址是一樣的。然后我們遍歷這個(gè)數(shù)組并打印每個(gè)元素的內(nèi)存地址。在我們 的計(jì)算機(jī)中 int 是四個(gè)字節(jié)的,數(shù)組內(nèi)存是連續(xù)的,因此每個(gè)int型元素地址之間相差4。

在最后一行,我們打印了數(shù)組的大小,數(shù)組的大小等于sizeof(type)乘上數(shù)組元素的數(shù)量。這里的數(shù)組有5個(gè)int型變量,每一個(gè)占用4字節(jié),因此整個(gè)數(shù)組大小為20字節(jié)。

結(jié)構(gòu)體地址

在C語言中,結(jié)構(gòu)體一般是連續(xù)的內(nèi)存區(qū)域,但也不一定是絕對連續(xù)的區(qū)域。和數(shù)組類似,它們能存儲多種數(shù)據(jù)類型,但不同于數(shù)組的是,它們能存儲不同的數(shù)據(jù)類型。

  1. struct measure { 
  2.   char category; 
  3.   int width; 
  4.   int height; 
  5. }; 
  6.   
  7. // declare and populate the struct 
  8. struct measure ball; 
  9. ball.category = 'C'
  10. ball.width = 5; 
  11. ball.height = 3; 
  12.   
  13. // print the addresses of the struct and its members 
  14. printf("address of ball = %p\n", (void *)(&ball)); 
  15. printf("address of ball.category = %p\n", (void *)(&ball.category)); 
  16. printf("address of ball.width = %p\n", (void *)(&ball.width)); 
  17. printf("address of ball.height = %p\n", (void *)(&ball.height)); 
  18.   
  19. // print the size of the struct 
  20. printf("sizeof(ball) = %lu\n"sizeof(ball)); 

運(yùn)行后的輸出結(jié)果如下:

  1. address of ball = 0x7fffd1510060 
  2. address of ball.category = 0x7fffd1510060 
  3. address of ball.width = 0x7fffd1510064 
  4. address of ball.height = 0x7fffd1510068 
  5. sizeof(ball) = 12 

在這個(gè)例子中我們定義了一個(gè)結(jié)構(gòu)體measure,然后聲明了該結(jié)構(gòu)體的一個(gè)實(shí)例ball,我們賦值給它的width、height以及 category成員,然后打印出ball的地址。與數(shù)組類似,結(jié)構(gòu)體也代表了它首元素的地址。然后打印了它每一個(gè)成員的地址。category是第一個(gè) 成員,它與ball具有相同的地址。width后面是height,它們都具有比category更高的地址。

你可能會想因?yàn)閏ategory是一個(gè)字符,而字符型變量占用1字節(jié),因此width的地址應(yīng)該比開始出高1個(gè)字節(jié)。從輸出來看這不對。 根據(jù)C99標(biāo)準(zhǔn)(§6.7.2.1),為邊界對齊,結(jié)構(gòu)體可以給成員增加填充字節(jié)。它不會記錄數(shù)據(jù)成員,但會增加額外的字節(jié)。在實(shí)際中,大多數(shù)的編譯器會 使結(jié)構(gòu)體中的每個(gè)成員與結(jié)構(gòu)體最大的成員有相同大小,

在我們的例子中,你可以看到char實(shí)際上占用4字節(jié),整個(gè)struct占用12個(gè)字節(jié)。都發(fā)生了什么?

1.struct變量指向struct首元素的地址

2.不要假設(shè)struct的成員是與其它區(qū)域分離的大量特殊的字節(jié),它們也許有邊界字節(jié)或者內(nèi)存并不連續(xù)。使用地址操作符&來獲得成員的地址

3.使用sizeof(struct instance)來獲得struct的總大小,不用假設(shè)它是各個(gè)成員域的大小總和,也許還有補(bǔ)充。

結(jié)論

喜歡這篇博文可以幫你理解更多的在C中如何操作不同的數(shù)據(jù)類型的地址。在以后的博文中,我們將會繼續(xù)研究一下指針和數(shù)組的基礎(chǔ)。

原文鏈接:http://denniskubes.com/2012/08/17/basics-of-memory-addresses-in-c/

譯文鏈接:http://blog.jobbole.com/44845/

責(zé)任編輯:陳四芳 來源: 伯樂在線
相關(guān)推薦

2017-07-25 15:09:48

Linux地址轉(zhuǎn)化

2015-09-29 08:51:59

內(nèi)存地址主引導(dǎo)

2023-12-08 14:32:02

C語言編程文件操作

2011-05-11 15:45:50

內(nèi)存管理Objective-C

2021-12-16 06:52:33

C語言內(nèi)存分配

2022-01-13 10:30:21

C語言內(nèi)存動(dòng)態(tài)

2021-06-01 07:16:21

C語言基礎(chǔ)代碼

2021-11-10 10:48:36

C++函數(shù)指針

2024-04-29 13:50:00

2010-01-19 14:45:35

C++語言

2021-04-27 13:56:49

內(nèi)存.映射地址

2020-10-19 09:34:04

C語言內(nèi)存錯(cuò)誤編程語言

2021-02-21 12:09:32

C 語言基礎(chǔ)語法

2021-02-20 06:13:18

C 語言C++

2023-05-03 21:49:13

2022-11-02 07:23:06

2015-05-05 14:40:31

2020-11-04 08:37:37

C語言C++內(nèi)存

2011-07-15 09:20:52

C語言文件操作

2021-02-11 08:25:17

C 語言C++ 基礎(chǔ)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产日韩欧美激情 | 国产免费又黄又爽又刺激蜜月al | 国产一区二区三区精品久久久 | 看特级黄色片 | 中文字幕视频在线 | 午夜看片网站 | 一区二区国产精品 | 亚洲精品一区二区在线观看 | 91免费看片 | 国产精品欧美一区二区三区 | 国产精品一区在线 | 五月激情婷婷六月 | 视频一区二区三区四区五区 | 国产精品久久久亚洲 | 午夜视频在线观看网站 | 国产成人精品久久二区二区91 | 免费视频一区二区 | 91精品国产色综合久久不卡98 | 国产一级淫片a直接免费看 免费a网站 | 欧美日韩国产一区二区三区 | 一区二区在线免费观看 | 欧美美乳 | 久久久精| 国产精品久久av | 日韩国产一区二区三区 | 一区二区三区国产 | 国产福利视频在线观看 | 女同久久 | 国产精品欧美一区二区三区不卡 | 一级午夜aaa免费看三区 | 久久久国产一区二区三区 | 色桃网| 99热在线观看精品 | 久久毛片| 亚洲bt 欧美bt 日本bt | 欧美一区二区三区视频 | 久久伊人一区二区 | 久久久国产精品 | 蜜桃传媒一区二区 | 精品国产乱码久久久久久丨区2区 | 亚洲一二三区精品 |