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

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語言指針加1引發(fā)的思考

jf_BxU6dNQb ? 來源:混說Linux ? 2023-01-29 11:31 ? 次閱讀

1. 問題背景

最近有小伙伴對于 C 語言中指針的運算有點疑問:指針變量加 1 之后,到底向后偏移了幾個字節(jié)呢?

示例代碼如下,這段代碼運行在32位CPU平臺上:

#include

#pragmapack(1)
structtree
{
intheight;
intage;
chartag;
};
#pragmapack()

intmain()
{
charbuffer[512];
char*tmp_ptr=NULL;
structtree*t_ptr=NULL;
char*t_ptr_new=NULL;

tmp_ptr=buffer;
t_ptr=(structtree*)tmp_ptr;
t_ptr_new=(char*)(t_ptr+1);

printf("t_ptr_newpointtobuffer[%ld]
",t_ptr_new-tmp_ptr);

return0;
}

請問,指針變量 t_ptr_new 指向數(shù)組 buffer 的哪個位置?

如果能快速得出答案,恭喜你,已經(jīng)掌握指針?biāo)阈g(shù)運算的原理,以及結(jié)構(gòu)體占用空間大小的計算方法。如果不能,也不要氣餒,正好可以將這部分欠缺的知識補充上。下面,讓我們來逐步揭開它的內(nèi)幕。

2. 結(jié)構(gòu)體

C 語言中 struct 聲明創(chuàng)建一個數(shù)據(jù)類型(結(jié)構(gòu)體),能將不同類型的對象聚合到一個對象中,用名字來引用結(jié)構(gòu)體的各個組成部分。結(jié)構(gòu)體的所有組成部分都存放在一段連續(xù)的內(nèi)存中。指向結(jié)構(gòu)的指針就是結(jié)構(gòu)體第一個成員的地址。

示例中結(jié)構(gòu)體類型定義:

#pragmapack(1)
structtree
{
intheight;
intage;
chartag;
};
#pragmapack()

結(jié)構(gòu)體內(nèi)部有三個成員變量,其中兩個為 int 型,一個 char 型。編譯器按照成員列表順序挨個給每個成員分配內(nèi)存。此結(jié)構(gòu)體占用的內(nèi)存空間是多少個字節(jié)呢?

height 和 age 各占用4個字節(jié),tag 占用 1 個字節(jié)。那結(jié)構(gòu)體占用的空間就是 9 個字節(jié)唄。是這樣嗎?

讓我們先來了解一個概念:數(shù)據(jù)對齊

數(shù)據(jù)對齊

許多計算機系統(tǒng)對基本的數(shù)據(jù)類型的合法地址做了一些限制。要求某種類型對象的地址必須是某個值(通常為2、4、8)的倍數(shù)。對齊原則是:任何占用 K 字節(jié)空間大小的基本對象,其地址必須是 K 的倍數(shù)。

由此,編譯器可能需要在結(jié)構(gòu)體成員內(nèi)存的分配中插入間隙,保證每個結(jié)構(gòu)成員都滿足它的對齊要求。或者需要在結(jié)構(gòu)體的末尾加入填充,從而使得結(jié)構(gòu)體數(shù)組中的每個元素都會滿足它的對齊要求。

本例中,結(jié)構(gòu)體的首地址滿足 4 字節(jié)對齊(第一個成員類型為 int)要求后,height、age、tag 三個成員均滿足對齊原則。不過要考慮下面的聲明:

Structtreea[4];

如果分配 9 個字節(jié),就不能滿足數(shù)組 a 的每個元素的對齊要求。

假設(shè)數(shù)組的起始地址為 x,則每個元素的地址分別為 x、x+9、x+18、x+27,有三個元素不滿足對齊原則。由此,編譯器會為結(jié)構(gòu) tree 分配 12 個字節(jié),最后 3 個字節(jié)是補充的空間(浪費的空間)。

pragma pack()

注意編譯指令,#pragma pack(1) 和 #pragma pack()

pragma pack 的主要作用就是改變編譯器的內(nèi)存對齊方式。

在不使用這條指令的情況下,編譯器采取默認(rèn)方式對齊。這兩條編譯預(yù)處理指令,使得在這之間定義的結(jié)構(gòu)體按照 1 字節(jié)方式對齊。在本例中,使用這兩條指令的效果是,編譯器不會在結(jié)構(gòu)體尾部填充空間了

結(jié)構(gòu)體大小

最終,這個結(jié)構(gòu)體占用的內(nèi)存空間大小為 9 個字節(jié)。

3. 理解指針

指針定義

每個指針都對應(yīng)一個類型。這個類型表明該指針指向的是哪一類對象。指針的類型不是機器碼中的一部分,而是C語言提供的一種抽象,幫助程序員避免尋址錯誤。

每個指針都有一個值。這個值是某個指定類型的對象的地址。

示例代碼中

structtree*t_ptr=NULL;

這語句是什么意思呢?其含義為:定義一個指針變量 t_ptr 并賦予了初值 NULL。

詳細(xì)解釋:星號 “*” 說明標(biāo)識符 t_ptr為 “一個指向…的指針”;struct tree 為類型說明符;可知,t_ptr 為指向結(jié)構(gòu)體 tree 類型的指針。

指針的類型由指向?qū)ο蟮臄?shù)據(jù)類型和星號 “*” 組合起來表示。例如,指針 t_ptr 的指針類型為 “struct tree *”。

示例代碼中,t_ptr_new 和 tm_ptr 為指向 char 類型的指針,并賦初始值NULL。

NULL 指針

C語言標(biāo)準(zhǔn)中定義了 NULL 指針,作為一種特殊的指針變量,其指向的內(nèi)容為空(即不指向任何東西)。將其賦值給某個指針變量,表示該指針目前并未指向任何東西。

數(shù)組的名字

一個數(shù)組的名字也是一種指針,但這個指針的值是不能改變的。這種指針永遠(yuǎn)指向數(shù)組中的第一個元素,其指向的類型為數(shù)組元素的數(shù)據(jù)類型。

示例代碼:

char buffer[512];

數(shù)組名字 buffer 為指向 char 數(shù)據(jù)類型的指針,它指向數(shù)組的首個元素 buffer[0]。

4. 指針轉(zhuǎn)換

通過類型轉(zhuǎn)換,可以將指針從一種類型轉(zhuǎn)換為另一種形式,改變的只是它的類型,值是不會改變的。

C語言中的類型轉(zhuǎn)換有兩種:隱式類型轉(zhuǎn)換和強制類型轉(zhuǎn)換。

示例代碼:

t_ptr_new=(char*)(t_ptr+1);

通過 “(char *)” 強制將 struct tree * 類型的指針轉(zhuǎn)換為 char * 類型,并將其賦值給一個 char * 類型的指針。如果去掉 “(char *)”,在編譯過程中,編譯器會根據(jù) “=” 左側(cè)變量的類型自動進(jìn)行轉(zhuǎn)換,但會產(chǎn)生告警信息。告警信息如下:

example.c:Infunction‘main’:
example.c12:warning:assignmentfromincompatiblepointertype[-Wincompatible-pointer-types]
t_ptr_new=(t_ptr+1);

本例中用強制類型轉(zhuǎn)換,一方面是為了消除編譯過程產(chǎn)生的警告,另一方面是為了使程序便于理解。

5. 指針運算

C語言的指針運算有兩種形式

第一種:指針 ± 整數(shù)

這種計算出來的值,會根據(jù)該指針指向的某種數(shù)據(jù)類型的大小進(jìn)行伸縮。例如,指針的值為 x,指向的數(shù)據(jù)類型大小為 L,整數(shù)為 n,則計算出來的結(jié)果值為 x + n * L

示例代碼,

t_ptr_new=(char*)(t_ptr+1);

此表達(dá)式等價于(a_ptr 符號在此處是為了便于理解而添加):

a_ptr=(t_ptr+1);
t_ptr_new=(char*)a_ptr;

指針 t_ptr 加 1(t_ptr + 1)的結(jié)果,會根據(jù)數(shù)據(jù)類型 struct tree 的大小進(jìn)行增加。假設(shè)指針 t_ptr 的值為 x(即地址值為 x),而結(jié)構(gòu)體類型 tree 的大小為 9 字節(jié),則 t_ptr + 1 的值為 x+9。然后,將此結(jié)果進(jìn)行強制類型轉(zhuǎn)換后,賦值給指針變量 t_ptr_new。

第二種:指針 – 指針

只有當(dāng)兩個指針都指向同一個數(shù)組中的元素時,計算才有意義。

減法運算的值是兩個指針在內(nèi)存中的距離(等于兩個地址之差除以該元素數(shù)據(jù)類型的大小)。兩個指針相減的結(jié)果的類型是 ptrdiff_t,它是一種有符號整數(shù)類型。

如果兩個指針值(地址值)的差值為 12 字節(jié),每個元素占用 4 個字節(jié),則兩個指針相減得到的結(jié)果將是 3(兩個指針的差值 12 將除以每個元素的長度 4)。

示例代碼

printf("t_ptr_newpointtobuffer[%ld]
",t_ptr_new-tmp_ptr);

由以上分析,兩個指針相減(t_ptr_new - tmp_ptr),地址差值為 9 字節(jié),而數(shù)組中每個元素的大小為 1 字節(jié)(char類型數(shù)據(jù)),則指針相減得到結(jié)果為 9(9字節(jié)/1字節(jié))。

6. 綜上分析

有了以上分析的基礎(chǔ),讓我們看看最終答案是如何得出的。

tmp_ptr=buffer;

tmp_ptr 指針指向數(shù)組 buffer 的第 0 個元素,即 buffer[0]。

t_ptr=(structtree*)tmp_ptr;

將指針tmp_ptr強制轉(zhuǎn)換為 struct tree * 類型的指針后,賦值給指針變量 t_ptr。

t_ptr_new=(char*)(t_ptr+1);

這個表達(dá)式是問題的關(guān)鍵。t_ptr + 1 運算得到的結(jié)果指針指向下一個結(jié)構(gòu)體 tree 元素,而結(jié)構(gòu)體占用的空間大小為9個字節(jié),因此指針加 1 后,實際偏移了 9 個字節(jié)。經(jīng)過強制類型轉(zhuǎn)換后,賦值給指針 t_ptr_new。

printf("t_ptr_newpointtobuffer[%ld]
",t_ptr_new-tmp_ptr);

t_ptr_new - tmp_ptr 運算得到結(jié)果是 9。由于 tmp_ptr 指向數(shù)組的第 0 個元素buffer[0],則 t_ptr_new 指向數(shù)組的第 9 個元素buffer[9]。

最終答案

指針加 1 后,偏移 9 個字節(jié);t_ptr_new指向buffer數(shù)組的第 9 個元素。打印輸出結(jié)果如下:

t_ptr_new point to buffer[9]

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    10880

    瀏覽量

    212210
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7608

    瀏覽量

    137134
  • 指針
    +關(guān)注

    關(guān)注

    1

    文章

    480

    瀏覽量

    70582
  • 數(shù)組
    +關(guān)注

    關(guān)注

    1

    文章

    417

    瀏覽量

    25980
  • 指針變量
    +關(guān)注

    關(guān)注

    0

    文章

    17

    瀏覽量

    7241

原文標(biāo)題:C語言指針加 1 引發(fā)的思考

文章出處:【微信號:混說Linux,微信公眾號:混說Linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    C語言中空指針和野指針的概念及產(chǎn)生原因

    C語言中,指針是一種非常強大和靈活的工具,但同時也容易引發(fā)一些問題,其中包括空指針和野指針
    發(fā)表于 08-16 16:18 ?1478次閱讀

    干貨知識分享—C語言指針思考

    是段錯誤。本文引用地址:http://www.embedu.org/Column/7260.html本文將以兩道典型的面試題為切入點,引發(fā)我們對于C語言指針
    發(fā)表于 01-12 17:05

    C語言入門教程-指針

    指針C語言中,指針被廣泛使用。所以要想完整地掌握C語言,您需要對
    發(fā)表于 07-29 11:30 ?672次閱讀

    C語言指針電子教程

    本資料是一份不錯的關(guān)于C語言指針的電子教程,希望對大家有所幫助... 指針簡介 指針C
    發(fā)表于 07-30 16:00 ?77次下載

    C語言指針函數(shù)和函數(shù)指針詳細(xì)介紹

    C語言指針函數(shù)和函數(shù)指針詳細(xì)介紹。。。。。。。
    發(fā)表于 03-04 15:27 ?5次下載

    c語言函數(shù)指針定義,指針函數(shù)和函數(shù)指針的區(qū)別

     往往,我們一提到指針函數(shù)和函數(shù)指針的時候,就有很多人弄不懂。下面就由小編詳細(xì)為大家介紹C語言中函數(shù)指針
    發(fā)表于 11-16 15:18 ?3629次閱讀

    C語言的精髓——指針詳解

    C語言的精髓——指針詳解
    發(fā)表于 11-30 14:43 ?17次下載

    為什么C語言要引入指針_引入指針的好處是什么

    讓你知道什么是 C語言 指針,為什么用指針,從此不在害怕指針
    的頭像 發(fā)表于 07-28 10:12 ?2.2w次閱讀

    2.5 C語言入職例程二:指針

    2.5.1 強化指針概念指針C語言中最基本且很重要的概念,某種程度上甚至可以說:指針C
    發(fā)表于 01-13 13:33 ?1次下載
    2.5	<b class='flag-5'>C</b><b class='flag-5'>語言</b>入職例程二:<b class='flag-5'>指針</b>

    C語言中的指針(重點)超詳細(xì)

    C語言中的指針1指針是什么2、指針指針類型2.1
    發(fā)表于 01-13 14:10 ?11次下載
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>中的<b class='flag-5'>指針</b>(重點)超詳細(xì)

    C指針1引發(fā)思考

    1. 問題背景 最近有小伙伴對于 C 語言中指針的運算有點疑問:指針變量 1 之后,到底向后偏
    發(fā)表于 01-26 10:07 ?450次閱讀

    C語言進(jìn)階】C語言指針的高階用法

    C語言進(jìn)階】C語言指針的高階用法
    的頭像 發(fā)表于 08-31 13:24 ?2352次閱讀

    C語言指針1引發(fā)的問題與思考

    如果能快速得出答案,恭喜你,已經(jīng)掌握指針算術(shù)運算的原理,以及結(jié)構(gòu)體占用空間大小的計算方法。
    的頭像 發(fā)表于 02-08 16:41 ?1328次閱讀

    C語言中的懸空指針和野指針是什么意思?

    提起C語言大部分開發(fā)者很自然就會想到指針二字,沒錯,作為C的核心和靈魂,它的地位咱們就不再贅述了,今天我們想跟大家講的是指針中的兩個特有名詞
    的頭像 發(fā)表于 02-09 17:20 ?1115次閱讀

    詳解C語言指針底層基本原理

    說到指針,估計還是有很多小伙伴都還是云里霧里的,有點“知其然,而不知其所以然”。但是,不得不說,學(xué)了指針C語言才能算是入門了。指針
    的頭像 發(fā)表于 04-06 10:43 ?1285次閱讀
    主站蜘蛛池模板: jizz老太婆| 中国明星16xxxxhd| 末班车动漫无删减免费| 黄桃AV无码免费一区二区三区| 国产黄A片在线观看永久免费麻豆| 久久永久免费视频| 国家产午夜精品无人区| 国产精品私人玩物在线观看| 国产成人免费高清在线观看| 中文字幕99香蕉在线| 亚洲视频免费观看| 亚洲伊人网站| 再深点灬舒服灬太大了在线视频| 亚洲视频一| 亚洲欧美高清在线精品一区| 亚洲人视频在线| 夜夜精品视频一区二区| 伊人久久综合| 《乳色吐息》无删减版在线观看 | 成人精品视频| 超级最爽的乱淫片免费| wwww晚晚干| 高H短篇辣肉纯肉| 国产精品久久久久久人妻香蕉 | 蜜臀AV久久国产午夜福利软件| 美女伸开两腿让我爽| 免费一级毛片在线观看| 欧美内射AAAAAAXXXXX| 日产亚洲一区二区三区| 无码AV熟妇素人内射V在线| 亚洲成人免费看| 一攻多受h嗯啊巨肉bl巨污| 2019天天射干网站| seyeye高清视频在线| 妇少水多18P蜜泬17P亚洲乱| 国产精品v片在线观看不卡| 国产在线精品亚洲观看不卡欧美 | 野花日本高清在线观看免费吗| 综合色一色综合久久网vr| 99久热这里精品免费| 大学生一级毛片免费看|