最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言零基礎(chǔ)講解指針和數(shù)組

 更新時間:2022年04月18日 16:48:24   作者:清風(fēng)自在 流水潺潺  
由于數(shù)據(jù)的表現(xiàn)形式多種多樣,還有字符型和其它的數(shù)值類型,因此僅有基本數(shù)據(jù)類型是不夠的。是否可以通過基本數(shù)據(jù)類型的組合抽象構(gòu)造其它的數(shù)據(jù)類型呢?下面是小編為大家?guī)淼腃語言數(shù)組與指針詳解的知識

一、指針和數(shù)組分析-上

1.數(shù)組的本質(zhì)

  • 數(shù)組是一段連續(xù)的內(nèi)存空間
  • 數(shù)組的空間大小為 sizeof(array_type) * array_size
  • 數(shù)組名可看做指向數(shù)組第一個元素的常量指針

下面看一段代碼:

#include <stdio.h>
 
int main()
{
    int a[5] = {0};
    int* p = NULL;
    
    printf("a = 0x%X\n", (unsigned int)(a));
    printf("a + 1 = 0x%X\n", (unsigned int)(a + 1));
    
    printf("p = 0x%X\n", (unsigned int)(p));
    printf("p + 1 = 0x%X\n", (unsigned int)(p + 1));
    
    return 0;
}

輸出結(jié)果如下:

通過這段代碼說明指針運算是合法的。

2.指針的運算

指針是一種特殊的變量,與整數(shù)的運算規(guī)則為

p + n; <-->(unsigned int)p + n*sizeof(*p);

結(jié)論∶

當(dāng)指針 p 指向一個同類型的數(shù)組的元素時:p+1 將指向當(dāng)前元素的下一個元素;p-1 將指向當(dāng)前元素的上一個元素。

  • 指針之間只支持減法運算
  • 參與減法運算的指針類型必須相同

p1- p2; <--> ((unsigned int)p1 - (unsigned int)p2) / sizeof(type);

注意:

  • 只有當(dāng)兩個指針指向同一個數(shù)組中的元素時,指針相減才有意義,其意義為指針所指元素的下標差
  • 當(dāng)兩個指針指向的元素不在同一個數(shù)組中時,結(jié)果未定義

下面看一段簡單的指針運算代碼:

#include <stdio.h>
 
int main()
{
    char s1[] = {'H', 'e', 'l', 'l', 'o'};
    int i = 0;
    char s2[] = {'W', 'o', 'r', 'l', 'd'};
    char* p0 = s1;
    char* p1 = &s1[3];
    char* p2 = s2;
    int* p = &i;
	
    printf("%d\n", p0 - p1);
    //printf("%d\n", p0 + p2);  //ERROR
    printf("%d\n", p0 - p2);
    //printf("%d\n", p0 - p);   //ERROR
    //printf("%d\n", p0 * p2);  //ERROR
    //printf("%d\n", p0 / p2);  //ERROR
	
    return 0;
}

輸出結(jié)果如下:

注意兩個指針指向不同的數(shù)組,雖然它們兩相減符合語法,但是最后的結(jié)果肯定沒有意義。

再來看一段指針運算的應(yīng)用代碼:

#include <stdio.h>
 
#define DIM(a) (sizeof(a) / sizeof(*a))
 
int main()
{
    char s[] = {'H', 'e', 'l', 'l', 'o'};
    char* pBegin = s;
    char* pEnd = s + DIM(s); // Key point
    char* p = NULL;
    
    printf("pBegin = %p\n", pBegin);
    printf("pEnd = %p\n", pEnd);
    
    printf("Size: %d\n", pEnd - pBegin);
	
    for(p=pBegin; p<pEnd; p++)
    {
        printf("%c", *p);
    }
    
    printf("\n");
   
    return 0;
}

輸出結(jié)果如下:

注意以下幾點:

  • 數(shù)組大小的計算方法:#define DIM(a) (sizeof(a) / sizeof(*a))
  • char* pEnd = s + DIM(s); // Key point ==> pEnd 指向 'o' 后面的地址 ==> 這在 C 語言中是一個擦邊球的邊界位置,也是一個技巧,在這個邊界位置可以認為該指針是合法的,可以和其他指針進行比較運算和減法運算等,在 C++ 標準庫里面也合法

3.指針的比較

  • 指針也可以進行關(guān)系運算 (<,<=,>,>=)
  • 指針關(guān)系運算的前提是同時指向同一個數(shù)組中的元素
  • 任意兩個指針之間的比較運算(==,!=)無限制
  • 參與比較運算的指針類型必須相同

4.小結(jié)

  • 數(shù)組聲明時編譯器自動分配一片連續(xù)的內(nèi)存空間
  • 指針聲明時只分配了用于容納地址值的 4 字節(jié)空間
  • 指針和整數(shù)可以進行運算,其結(jié)果為指針
  • 指針之間只支持減法運算,其結(jié)果為數(shù)組元素下標差
  • 指針之間支持比較運算,其類型必須相同

二、指針與數(shù)組分析-下 

1.數(shù)組的訪問方式

以下標的形式訪問數(shù)組中的元素

以指針的形式訪問數(shù)組中的元素

2.下標形式 VS 指針形式

  • 指針以固定增量在數(shù)組中移動時,效率高于下標形式
  • 指針增量為1且硬件具有硬件增量模型時,效率更高
  • 下標形式與指針形式的轉(zhuǎn)換

a[n] <--> *(a +n) <--> *(n + a) <--> n[a]

注意:現(xiàn)代編譯器的生成代碼優(yōu)化率已大大提高,在固定增量時,下標形式的效率已經(jīng)和指針形式相當(dāng);但從可讀性和代碼維護的角度來看,下標形式更優(yōu)。

下面看一個數(shù)組的訪問方式代碼:

#include <stdio.h>
 
int main()
{
    int a[5] = {0};
    int* p = a;
    int i = 0;
    
    for(i=0; i<5; i++)
    {
        p[i] = i + 1;
    }
    
    for(i=0; i<5; i++)
    {
        printf("a[%d] = %d\n", i, *(a + i));
    }
    
    printf("\n");
    
    for(i=0; i<5; i++)
    {
        i[a] = i + 10;
    }
    
    for(i=0; i<5; i++)
    {
        printf("p[%d] = %d\n", i, p[i]);
    }
    
    return 0;
}

輸出結(jié)果如下:

注意這個奇怪的寫法:i[a] = i + 10; ==> a[i] = i + 10;

下面通過一個實例,說明數(shù)組和指針的不同:

ext.c:

int a[] = {1, 2, 3, 4, 5};

test.c:

#include <stdio.h>
 
int main()
{
    extern int a[];
    
    printf("&a = %p\n", &a);
    printf("a = %p\n", a);
    printf("*a = %d\n", *a);
 
    return 0;
}

輸出結(jié)果如下:

下面來驗證一下數(shù)組名究竟是不是指針,將 test.c 改成:

#include <stdio.h>
 
int main()
{
    extern int* a;
    
    printf("&a = %p\n", &a);
    printf("a = %p\n", a);
    printf("*a = %d\n", *a);
 
    return 0;
}

輸出結(jié)果如下:

ext.c 中 a[ ] 的地址為 0x804a014,test.c 中的extern int* a; 只是申明標識符 a,編譯器會認為在這之前就已經(jīng)給了地址值,就是 0x804a014,所以printf("a = %p\n", a); 就是打印0x804a014 地址中的 4 個字節(jié)的數(shù),也就是 a[ ] 數(shù)組中的第一個元素 1,所以打印 0x1,*a 就是取 0x1 地址中的數(shù),但是這個地址值是留給操作系統(tǒng)的,不可訪問,訪問就會產(chǎn)生段錯誤。

3.a 和 &a 的區(qū)別

  • a 為數(shù)組首元素的地址
  • &a 為整個數(shù)組的地址
  • a 和 &a 的區(qū)別在于指針運算

這個就能看出 a + 1 和 &a + 1 的不同,a + 1 增加的步長是一個元素的大小,&a + 1 則是增加的步長是整個數(shù)組的大小。

下面看一個指針運算的經(jīng)典問題:

#include <stdio.h>
 
int main()
{
    int a[5] = {1, 2, 3, 4, 5};
    int* p1 = (int*)(&a + 1); 
    int* p2 = (int*)((int)a + 1);
    int* p3 = (int*)(a + 1);
    
    printf("%d, %d, %d\n", p1[-1], p2[0], p3[1]);
    
    return 0;
}

輸出結(jié)果如下:

p1[-1] 就是 *(p1 - 1),由于 p1 指向的元素是 5 后面的位置,減 1 之后就指向了 5;p2 的地址是 0x804a015(注意 linux 系統(tǒng)為小端系統(tǒng)),*p2 就是 0x02000000,對應(yīng)十進制的值就是 33554432;p3 的地址為 &a[1],所以 p3[1] 就是 3 了。

4.數(shù)組參數(shù)

數(shù)組作為函數(shù)參數(shù)時,編譯器將其編譯成對應(yīng)的指針

結(jié)論:一般情況下,當(dāng)定義的函數(shù)中有數(shù)組參數(shù)時,需要定義另一個參數(shù)來標示數(shù)組的大小。

下面看一段代碼:

#include <stdio.h>
 
void func1(char a[5])
{
    printf("In func1: sizeof(a) = %d\n", sizeof(a));
    
    *a = 'a';
    
    a = NULL;
}
 
void func2(char b[])
{
    printf("In func2: sizeof(b) = %d\n", sizeof(b));
    
    *b = 'b';
    
    b = NULL;
}
 
int main()
{
    char array[10] = {0};
    
    func1(array);
    
    printf("array[0] = %c\n", array[0]);
    
    func2(array);
    
    printf("array[0] = %c\n", array[0]);
    
    return 0;
}

輸出結(jié)果如下:

這段代碼就說明數(shù)組參數(shù)退化成指針,因為 sizeof(a) 為 4 個字節(jié),而不是 5 個字節(jié)。

5.小結(jié)

數(shù)組名和指針僅使用方式相同

  • 數(shù)組名的本質(zhì)不是指針
  • 指針的本質(zhì)不是數(shù)組

數(shù)組名并不是數(shù)組的地址,而是數(shù)組首元素的地址

函數(shù)的數(shù)組參數(shù)退化為指針

到此這篇關(guān)于C語言零基礎(chǔ)講解指針和數(shù)組的文章就介紹到這了,更多相關(guān)C語言 指針和數(shù)組內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言新手練習(xí)之多維數(shù)組、結(jié)構(gòu)體及函數(shù)

    C語言新手練習(xí)之多維數(shù)組、結(jié)構(gòu)體及函數(shù)

    這篇文章主要給大家介紹了關(guān)于C語言新手練習(xí)之多維數(shù)組、結(jié)構(gòu)體及函數(shù)的相關(guān)資料,這些內(nèi)容在我們?nèi)粘i_發(fā)中經(jīng)常會遇到的,需要的朋友可以參考下
    2021-06-06
  • 淺析Boost智能指針:scoped_ptr shared_ptr weak_ptr

    淺析Boost智能指針:scoped_ptr shared_ptr weak_ptr

    雖然通過弱引用指針可以有效的解除循環(huán)引用,但這種方式必須在程序員能預(yù)見會出現(xiàn)循環(huán)引用的情況下才能使用,也可以是說這個僅僅是一種編譯期的解決方案,如果程序在運行過程中出現(xiàn)了循環(huán)引用,還是會造成內(nèi)存泄漏的
    2013-09-09
  • 基于Linux系統(tǒng)調(diào)用--getrlimit()與setrlimit()函數(shù)的方法

    基于Linux系統(tǒng)調(diào)用--getrlimit()與setrlimit()函數(shù)的方法

    本篇文章是對在Linux系統(tǒng)中調(diào)用getrlimit()與setrlimit()函數(shù)的方法進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • OpenCV利用霍夫變換實現(xiàn)交通車道線檢測

    OpenCV利用霍夫變換實現(xiàn)交通車道線檢測

    經(jīng)典霍夫變換用來檢測圖像中的直線,后來霍夫變換經(jīng)過擴展可以進行任意形狀物體的識別,例如圓和橢圓。本文就來利用霍夫變換實現(xiàn)交通車道線檢測,需要的可以參考一下
    2022-09-09
  • C語言實現(xiàn)簡單的聊天室功能

    C語言實現(xiàn)簡單的聊天室功能

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)簡單的聊天室功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C語言實現(xiàn)隨機抽獎程序

    C語言實現(xiàn)隨機抽獎程序

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)隨機抽獎程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • C++中的Lambda函數(shù)詳解

    C++中的Lambda函數(shù)詳解

    大家好,本篇文章主要講的是C++中的Lambda函數(shù)詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • C++ Boost Serialization庫超詳細獎金額

    C++ Boost Serialization庫超詳細獎金額

    Boost是為C++語言標準庫提供擴展的一些C++程序庫的總稱。Boost庫是一個可移植、提供源代碼的C++庫,作為標準庫的后備,是C++標準化進程的開發(fā)引擎之一,是為C++語言標準庫提供擴展的一些C++程序庫的總稱
    2022-12-12
  • 深入理解C/C++混合編程

    深入理解C/C++混合編程

    本篇文章是對C/C++混合編程進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • C語言自定義數(shù)據(jù)類型的結(jié)構(gòu)體、枚舉和聯(lián)合詳解

    C語言自定義數(shù)據(jù)類型的結(jié)構(gòu)體、枚舉和聯(lián)合詳解

    這篇文章主要給大家介紹了關(guān)于C語言自定義數(shù)據(jù)類型的結(jié)構(gòu)體、枚舉和聯(lián)合的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05

最新評論

饶平县| 南京市| 遂平县| 建昌县| 邵阳县| 类乌齐县| 兖州市| 宁夏| 五寨县| 桓台县| 莱阳市| 建瓯市| 肇州县| 磐石市| 内丘县| 海晏县| 筠连县| 平果县| 黄梅县| 项城市| 葫芦岛市| 布尔津县| 元阳县| 石门县| 大名县| 嘉黎县| 蕲春县| 广河县| 邓州市| 新乐市| 嘉禾县| 屯门区| 上虞市| 那曲县| 兴隆县| 东兰县| 宿迁市| 昭苏县| 南靖县| 南汇区| 安陆市|