日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C语言的数组名和对数组名取地址

發布時間:2023/12/20 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言的数组名和对数组名取地址 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

***************************************************

更多精彩,歡迎進入:http://shop115376623.taobao.com

***************************************************


相信不少的C語言初學者都知道,數組名相當于指針,指向數組的首地址,而函數名相當于函數指針,指向函數的入口地址。

現在有這樣一個問題,如果對數組名取地址,那得到的會是什么呢?很多人立刻會想到:給指針取地址,就是指針的指針,

即二級指針嘛!當然這樣的結論是錯誤的,不然這篇筆記也就沒有意義了。


下面我們來逐步分析,下面是一段驗證這個問題的代碼

Code:
  • #include<stdio.h>???
  • int?main() ??
  • { ??
  • ????int?a[10]; ??
  • ??
  • ????printf("a:/t%p/n",?a);????????? ??
  • ????printf("&a:/t%p/n",?&a);??????? ??
  • ????printf("a+1:/t%p/n",?a+1);????? ??
  • ????printf("&a+1:/t%p/n",?&a+1);?? ??
  • ??
  • ????return?0; ??
  • }??
  • ?

    大家可以編譯運行一下,我的輸出的結果是:

    Code:
  • /*???
  • a:??????????0012FF20??
  • &a:?????????0012FF20??
  • a+1:????????0012FF24??
  • &a+1:?????? 0012FF48??
  • */??
  • a和&a指向的是同一塊地址,但他們+1后的效果不同,a+1是一個元素的內存大小(增加4),而&a+1增加的是整個數組的內存

    大小(增加40)。既a和&a的指向和&a[0]是相同的,但性質不同!

    讀到這里,有很多朋友已經明白其中的機制了,如果還是有些模糊,請繼續往下看

    Code:
  • int?main() ??
  • { ??
  • ????int?a[10]; ??
  • ????printf("%d/n",sizeof(a)); ??
  • ????return?0; ??
  • }??
  • 這段代碼會輸出整個數組的內存大小,而不是首元素的大小,由此我們是否聯系到,sizeof(a)這里的a和
    &a有些相同之處呢?!? 是的,沒錯,&a取都得是整個數組的地址!既數組名取地址等價于對數組取地址。


    好了,讓我們總結一下,如果你還是不太理解,不用擔心,下面的概念很清晰


    其實a和 &a結果都是數組的首地址,但他們的類型是不一樣。
    a表示&a[0],也即對數組首元素取地址,a+1表示首地址+sizeof(元素類型)。
    &a雖然值為數組首元素地址,但類型為:類型 (*)[數組元素個數],所以&a+1大小為:首地址+sizeof(a)。


    還有這篇文章最初提到的指針的指針的那個錯誤結論,其實即使不懂上述內容,也應該判斷出結論是錯誤的,大家應該在了解數組名

    即是數組的首地址的同時,也要知道,數組名僅僅是“相當”于指針,而并非真的是指針,數組名是只是個常量(一個值為數組首元素

    地址的常量),所以不能進行++或者--運算。而常量更是無法取地址的,而之所以有&a,其實這里的a的意義早已經不是當初那個數組

    名了,它此時代表了整個數組。





    C語言數組首地址和數組名取地址區別 2010年11月24日 11:51

    申明:本文系原創,轉載時請注明出處,本人保留追究責任的權利。

    原文地址:http://hi.baidu.com/surfmygod/blog/item/53d44914cdb8a5d6a7ef3f13.html


    本文適用于機器為32位,編譯器為VC6.0

    先來看下面一個例子:
    main()
    {
    int a[5]={0x11121314,0x21222324,0x31323334,0x41424344,0x51525354};
    int *ptr1=(int *)(&a+1);
    int *ptr2=(int *)(a+1);
    printf("%x,%x",ptr1[-1],*ptr2);
    getch();
    }
    打印輸出的結果是多少?第4行&a是不是寫錯了?數組名怎么還取地址呢?
    你可以試著在軟件中編譯運行一下,結果是51525354,21222324,沒錯,就是它了。你可以試著寫以下程序
    再在計算機中編譯運行下:

    main()

    {

    int a[5]={0x11121314,0x21222324,0x31323334,0x41424344,0x51525354};

    printf("%p\n%p\n",a,&a);

    printf("%d\n%d\n",sizeof(a),sizeof(&a));

    printf("%p\n%p",&a+1,a+1);

    getch();

    }

    你可以看到前兩行a和&a打印的結果是一樣的(比如0012FF6C),后兩行的結果是都是20,而&a+1的結果是0012FF6C,

    即a的起始地址后移20字節。看到這里對于a和&a的區別是不是有些眉目了?不錯,a和&a的值雖然一樣,但是前者表示

    的是數組a的首地址,進階為數組元素長度,而后者也是表示數組a的首地址(或許有些人不同意我這個觀點,對地址

    取地址應該是指向指針的指針呀。不過你注意了沒有,a和&a值是一樣的,試想如果這里表示的是指向指針的指針,

    那么a的地址和指向a的指針的地址可能一樣么?

    兩個指針都指向數組首地址,怎么會是指向指針的指針?還有一點需要強調,對一個指針進行sizeof運算,32位系統

    下應該得到4,而對數組名進行sizeof運算得到的結果卻是20,這說明了什么?很顯然,數組名雖然能夠拿出來代表

    一個地址,但是它和指針還是有區別的,對它進行sizeof運算也不會得到指針的大小。不信?你可以試試sizeof(&a[0])

    和sizeof(a),看看結果是不是相同),

    但是是將整個數組作為一個對象來看待的,進階為整個數組長度。也就是說,a和&a雖然值相同,但是a是將所有數組

    元素看成一個個不同的個體來對待的,而&a是將整個數組作為一個整體來對待的。這里要強調的是,a+1和&a[1]其實

    是一樣的,都是代表a數組向后偏移一個元素的地址,你可以再用sizeof關鍵字打印一下兩個的值。但是a和&a[0]的

    意義相同么?若打印地址的話,兩者確實是一樣的,但是你也用sizeof打印下兩者,一樣么?再試試a+0呢?很顯然,

    a和a+0是有區別的,但是a+0和&a[0]是含義相同的。所以,你可以說a+i和&a[i]含義相同,但是絕不能說a和&a[0]

    或a+0含義相同。所以&a+1后移20位為&a+sizeof(&a),而a+1卻是a+sizeof(a[i])。

    (《C語言深度解剖》認為在32為系統下sizeof(&a)的值仍為4,我覺得是不對的。他覺得是VC6.0錯了,其實不止VC,

    其他很多編譯器得到的結果也不會是4,這說明a和&a在C中本來就不是作為指針來用的,只是具有指針的部分性質而已。)



    ptr1是將&a+1強轉為int類型指針,此時打印ptr1[-1]即將ptr指針前移sizeof(int)個字節,故打印結果是5。

    這樣一來后面的也明了了,a+1的值為在數組a的首地址上后移sizeof(int)個字節,然后強轉為int類型指針

    (其實強轉并沒有改變什么,原來類型即為整型指針,可以去掉強轉),最后輸出結果為21222324。


    再想一下,如果將第一例第五行改為int *ptr2=(int *)((int)a+1);打印結果會是什么?
    這里要考慮數據在計算機中的存儲模式:大端模式和小端模式。解釋一下:

    大端模式(Big_endian):字數據的高字節存儲在低地址中,而字數據的低字節則存放在高地址中。
    小端模式(Little_endian):字數據的高字節存儲在高地址中,而字數據的低字節則存放在低地址中。

    在大端模式下,a在計算機中存儲如下(從低地址到高地址,一個十六進制數代表內存的一個字節,下同):
    0x11 0x12 0x13 0x14 0x21 0x22 0x23 0x24 0x31 0x32 0x33 0x34 0x41 0x42 0x43 0x44 0x51 0x52 0x53 0x54

    在小端模式下,a在計算機中存儲如下:
    0x14 0x13 0x12 0x11 0x24 0x23 0x22 0x21 0x34 0x33 0x32 0x31 0x44 0x43 0x42 0x41 0x54 0x53 0x52 0x51

    (int)a表示將a的首地址強轉為整型數據(若原來是0012FF6C,轉換后仍為0012FF6C,但是這時已經不是表示地址而是一個
    十六進制整型數了),這時+1代表整型數(int)a加1(變為0012FF6D),再把結果強轉為整形指針,故指向的數據地址為0012FF6D, 即上述存儲去的第二個字節開始處。此時輸出*ptr2,即輸出a數組存儲區中第二到第五字節組成的一個整型數,若為大端模式則輸出 12131421,若為小端模式則輸出24111213。



    補充說明下,在vc6.0上,上面sizeof(&a)才是20,而在GCC ,以及之后的vc版本(如vs2005及之后版本)則是將&a完全視作一個指針,sizeof(&a)為4 (32位機器)


    二維數組名問題?
    轉自: ?http://zhidao.baidu.com/question/386658092.html

    int *p1[3], (*p2)[2], ** p, a[3][2];a) p1=a;是否語法正確? b) p2=a;呢? ? 為什么?請詳述原因。 c) p=a; 是否正確???可不可以認為二維數組名是一個指向指針的指針變量? a)不正確!p1是指針數組,他的元素是指針,但是他是數組,數組名不可以寫在賦值號左邊。b)正確!p2是數組指針,他可以指向一個數組。在這里他可以指向一個包含2個元素的數組。而二維數組的本質是指針數組,每個元素是一個 數組指針(這點是核心)。a[3][2] 的實質是:一個有3個元素的數組,每個元素是數組指針,該指針指向一個含有2個元素的數組(因為內存是個大的1維數組,所有東西在內存里都是1維數組)。#include <stdio.h>int main(void){ int (*p1)[2]; int a[3][2]; p1=a; printf("%p, %p\n",p1+2,a+2); while(1); return 0;}以上程序可以說明b是正確的。c:不正確!如果你做p++那么p的值只增加了4(一個指針大小),而不是增加8(一個 p[2] 大小) 其他網址:?http://topic.csdn.net/u/20100106/15/e5fa8fa6-555e-4729-a435-d1f8fdac5612.html


    示例程序:
    ?#if 1
    #include <stdio.h> #include <stdlib.h>


    int main() { int a[] = {1,2,3,4,5}; int *p1 = (int *)(a+1); int *p2 = (int *)(&a+1);? int *p3 = (int *)((int)a + 1); int *p4 = a;? printf("a is %p \n",a); printf("&a is %p \n",&a); printf("sizeof(a) = %d\n",sizeof(a)); printf("sizeof(&a) = %d\n",sizeof(&a)); printf("sizeof(p4) = %d \n",sizeof(p4));? printf("p1 = %p \n",p1); printf("p2 = %p \n",p2); printf("*p1 = %d\n",*p1); printf("p2[-1] = %d\n",p2[-1]); printf("*p3 = %d \n",*p3); printf("*(p2-1) = %d \n",*(p2-1)); ?? ? ? ? ? ? system("PAUSE"); ? ? return 0; }
    #endif

    總結

    以上是生活随笔為你收集整理的C语言的数组名和对数组名取地址的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。