日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
C語(yǔ)言內(nèi)存地址基礎(chǔ)

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

為伊犁等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及伊犁網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、伊犁網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

如果對(duì)『指針』、『地址』和『逆向引用』感到混亂,請(qǐng)看《C語(yǔ)言指針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è)存儲(chǔ)在2048位置的值。該字符是單字節(jié)的因此它只占用了索引為 2048 的位置。如果我們對(duì) 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è)地址。我們是通過(guò)使 用&操作符并+1或-1來(lái)獲取前后兩個(gè)地址的。在7-11行的第二個(gè)例子中我們做了差不多的事,除了聲明了一個(gè)int型變量,打印出它的地址以及 緊鄰它前后的地址。

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

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

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

數(shù)組地址

在C語(yǔ)言中,數(shù)組是相鄰的內(nèi)存區(qū)域,它存儲(chǔ)了大量相同數(shù)據(jù)類型的值(int、long、*char等等)。很多程序員第一次用C時(shí),會(huì)將數(shù)組當(dāng)做指針。那是不對(duì)的。指針存儲(chǔ)一個(gè)簡(jiǎn)單的內(nèi)存地址,而一個(gè)數(shù)組是一塊存儲(chǔ)多個(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ù)組本身的地址,注意我們沒(méi)有使用地址操作符 & 。這是因?yàn)閿?shù)組變量已經(jīng)代表了數(shù)組首元素的地址。你會(huì)看到數(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語(yǔ)言中,結(jié)構(gòu)體一般是連續(xù)的內(nèi)存區(qū)域,但也不一定是絕對(duì)連續(xù)的區(qū)域。和數(shù)組類似,它們能存儲(chǔ)多種數(shù)據(jù)類型,但不同于數(shù)組的是,它們能存儲(chǔ)不同的數(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更高的地址。

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

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

結(jié)論

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


文章題目:C語(yǔ)言內(nèi)存地址基礎(chǔ)
本文鏈接:http://m.5511xx.com/article/dpoecoj.html