欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言?指針數(shù)組進階詳解

 更新時間:2022年02月09日 10:56:54   作者:七憶歲和  
在C語言和C++等語言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來指向若干個字符串,使字符串處理更加方便、靈活

前言:指針與數(shù)組的知識往往讓我們無法給自己定位,似乎是懂了,但真的碰上了又一言難盡。接下來有一些關于指針與數(shù)組的知識和例題講解,來看看你對指針和數(shù)組到底有多了解吧!

指針與數(shù)組中的sizeof與strlen

sizeof

sizeof值關注占用空間的大小,單位是字節(jié),不關注元素的類型,是一個操作符。

strlen

strlen是計算字符串中\(zhòng)0之前出現(xiàn)了多少個字符,只針對字符串,是一個庫函數(shù)。

數(shù)組名

數(shù)組名是數(shù)組首元素地址,但是在這里有兩個例外:

(1)sizeof(數(shù)組名),這里的數(shù)組名表示的是整個數(shù)組,計算的是整個數(shù)組的大小,單位是字節(jié)。

(2)&數(shù)組名,這里的數(shù)組名也表示整個數(shù)組,取出的是數(shù)組的地址

除了上面兩種情況外,所有的數(shù)組名表示的都是數(shù)組首元素地址。

下面我們就來看一看數(shù)組、指針的一些運用

1、一維數(shù)組

整型數(shù)組

#include<stdio.h>
int main()
{
    //一維數(shù)組
    int a[] = {1,2,3,4};
 
    printf("%d\n",sizeof(a));// 16
    printf("%d\n",sizeof(a+0));// 4/8
    printf("%d\n",sizeof(*a));// 4
    printf("%d\n",sizeof(a+1));// 4/8
    printf("%d\n",sizeof(a[1]));// 4
    printf("%d\n",sizeof(&a));// 4/8
    printf("%d\n",sizeof(*&a));// 16
    printf("%d\n",sizeof(&a+1));// 4/8
    printf("%d\n",sizeof(&a[0]));// 4/8
    printf("%d\n",sizeof(&a[0]+1));// 4/8
 
    return 0;
}

接下來我們就一句一句講解:

sizeof(a)

數(shù)組名a單獨放在sizeof內(nèi)部,計算的是整個數(shù)組的大小,單位是字節(jié),所以計算結(jié)果:4*4=16個字節(jié)。

sizeof(a+0)

a沒有單獨存放,所以表示的是首元素的地址,a+0還是數(shù)組首元素的地址,是地址的話大小就是4/8個字節(jié)。(在32位環(huán)境下為4,64位環(huán)境下為8)

sizeof(*a)

a表示的是首元素的地址,*a就是對首元素的地址解引用,所以就是首元素,大小為4個字節(jié)

sizeof(a+1)

a表示首元素地址,a+1就是第二個元素的地址,是地址的話大小就是4/8個字節(jié)。

sizeof(a[1])

a[1]表示數(shù)組的第二個元素,大小是4個字節(jié)。

sizeof(&a)

&a表示的是整個數(shù)組的地址,數(shù)組的地址也是地址,所以大小為4/8個字節(jié)。

sizeof(*&a)

&a是數(shù)組的地址,類型是int(*)[4],是一個數(shù)組指針,如果解引用,訪問的就是4個int的數(shù)組,可以理解為*與&抵消效果,所以*&a相當于a,所以sizrof(a)是16。

sizeof(&a+1)

&a是數(shù)組地址,&a+1跳過整個數(shù)組后的地址,是地址就是4/8個字節(jié)大小。

sizeof(&a[0])

&a[0]取出的是數(shù)組第一個元素的地址,是地址就是4/8個字節(jié)大小。

sizeof(&a[0]+1)

&a[0]+1就是第二個元素的地址,是地址大小就是4/8個字節(jié)。

字符數(shù)組

#include<stdio.h>
int main()
{
    //字符數(shù)組
    char arr[] = {'a','b','c','d','e','f'};
 
    printf("%d\n", sizeof(arr));// 6
    printf("%d\n", sizeof(arr+0));// 4/8
    printf("%d\n", sizeof(*arr));// 1
    printf("%d\n", sizeof(arr[1]));// 1
    printf("%d\n", sizeof(&arr));// 4/8
    printf("%d\n", sizeof(&arr+1));// 4/8
    printf("%d\n", sizeof(&arr[0]+1));// 4/8
 
    printf("%d\n", strlen(arr));// 隨機值
    printf("%d\n", strlen(arr+0));// 隨機值
    printf("%d\n", strlen(*arr));// err
    printf("%d\n", strlen(arr[1]));// err
    printf("%d\n", strlen(&arr));// 隨機值
    printf("%d\n", strlen(&arr+1));// 隨機值
    printf("%d\n", strlen(&arr[0]+1));// 隨機值
 
    return 0;
}

1、sizeof

sizeof(arr)

arr作為數(shù)組名單獨存放在sizeof內(nèi)部,計算的是整個數(shù)組的大小,所以是6個字節(jié)。

sizeof(arr+0)

arr沒有單獨存放,所以這里的arr表示的是首元素地址,arr+0還是首元素地址,是地址就是4/8個字節(jié)大小。

sizeof(*arr)

arr表示數(shù)組的首元素地址,*arr表示的就是首元素,由于是char類型,所以是1字節(jié)。

sizeof(arr[1])

arr[1]就是數(shù)組中的第二個元素,大小是1字節(jié)。

sizeof(&arr)

&arr取出的是數(shù)組的地址,地址大小為4/8個字節(jié)。

sizeof(&arr+1)

&arr+1跳過了整個數(shù)組,還是地址,所以大小為4/8個字節(jié)。

sizeof(&arr[0]+1)

&arr[0]是第一個元素的地址,&arr[0]+1就是第二個元素的地址,地址就是4/8個字節(jié)。

2、strlen

strlen(arr)

arr是首元素地址,但是arr數(shù)組中沒有\(zhòng)0,計算的時候不知道什么時候停止,所以結(jié)果是隨機值。

strlen(arr+0)

arr+0還是首元素地址,同上

strlen(*arr)、strlen(arr[1])

strlen需要的是一個地址,從這個地址開始向后計算字符,直到碰上\0停止,統(tǒng)計字符的個數(shù),而*arr是首元素'a',也就是傳給strlen的是'a'的ASCII碼值97,strlen會把97作為起始地址,統(tǒng)計字符串,會形成內(nèi)存訪問沖突,所以會報錯!arr[1]也一樣,是第二個元素'b'。

strlen(&arr)

&arr是arr數(shù)組的地址,雖然類型和strlen的參數(shù)類型有所差異,但是傳參過去后,還是從第一個字符的位置向后數(shù)字符,而arr數(shù)組中沒有\(zhòng)0,所以結(jié)果還是隨機值。

strlen(&arr+1)

跳過整個數(shù)組,但還是不知道哪里會出現(xiàn)\0,所以結(jié)果還是隨機值。

strlen(&arr[0]+1)

&arr[0]表示首元素的地址,&arr[0]+1表示第二個元素的地址,也就是從第二個字符還是往后數(shù),但由于\0不能確定所以還是隨機值。

下面這個就用來自測吧!

#include<stdio.h>
int main()
{
    char arr[] = "abcdef";
 
    printf("%d\n", sizeof(arr));// 7 整個數(shù)組的大小,包括\0
    printf("%d\n", sizeof(arr+0));// 4/8
    printf("%d\n", sizeof(*arr));// 1
    printf("%d\n", sizeof(arr[1]));// 1
    printf("%d\n", sizeof(&arr));// 4/8
    printf("%d\n", sizeof(&arr+1));// 4/8
    printf("%d\n", sizeof(&arr[0]+1));// 4/8
 
    printf("%d\n", strlen(arr));// 6
    printf("%d\n", strlen(arr+0));// 6
    printf("%d\n", strlen(*arr));// err
    printf("%d\n", strlen(arr[1]));// err
    printf("%d\n", strlen(&arr));// 6
    printf("%d\n", strlen(&arr+1));// 隨機值
    printf("%d\n", strlen(&arr[0]+1));// 5
 
    return 0;
}

指針數(shù)組

#include<stdio.h>
int main()
{
    char *p = "abcdef";
 
    printf("%d\n", sizeof(p));// 4/8
    printf("%d\n", sizeof(p+1));// 4/8
    printf("%d\n", sizeof(*p));// 1
    printf("%d\n", sizeof(p[0]));// 1
    printf("%d\n", sizeof(&p));// 4/8
    printf("%d\n", sizeof(&p+1));// 4/8
    printf("%d\n", sizeof(&p[0]+1));// 4/8
 
    printf("%d\n", strlen(p));// 6
    printf("%d\n", strlen(p+1));// 5
    printf("%d\n", strlen(*p));// err
    printf("%d\n", strlen(p[0]));// err
    printf("%d\n", strlen(&p));// 隨機值
    printf("%d\n", strlen(&p+1));// 隨機值
    printf("%d\n", strlen(&p[0]+1));// 5
 
    return 0;
}

1、sizeof

sizeof(p)

p是一個指針變量,sizeof(p)計算的是指針變量大小,4/8個字節(jié)。

sizeof(p+1)

p是指針變量,用來存放地址的,p+1也是地址,地址大小就是4/8個字節(jié)。

sizeof(*p)

*p訪問的是字符a,大小1字節(jié)。

sizeof(p[0])

p[0]相當于*(p+0),相當于*p,同上。

sizeof(&p)

&p也是地址,是地址就是4/8個字節(jié)。

sizeof(&p+1)

&p是地址,+1是在內(nèi)存中跳過p變量后的地址,還是地址,所以為4/8字節(jié)。

sizeof(&p[0]+1)

p[0]就是a,&p[0]就是a的地址,&p[0]+1就是b的地址,是地址就是4/8個字節(jié)。

2、strlen

strlen(p)

這里的p是首元素地址,也就是'a'的地址,strlen(p)就是從'a'的位置向后求字符串的長度,長度是6。

strlen(p+1)

p是首元素地址,p+1就是第二個元素的地址,也就是'b',從b開始數(shù)直到\0,所以長度是5。

strlen(*p)、strlen(p[0])

*p、p[0]都是首元素'a',傳的是a的ASCII碼值,會有警報。

strlen(&p)、strlen(&p+1)

&p是指針p的地址,也就是算p的地址的字符串長度,由于不知道什么時候碰到\0,所以是隨機值;&p+1就是跳過p的地址訪問字符,\0未知,所以也是隨機值。如圖:

strlen(&p[0]+1)

&p[0]就是首元素地址,+1就是從第二個元素開始計算,長度為5;p[0]也可以看做*(p+0),也就是*p。

2、二維數(shù)組

#include<stdio.h>
int main()
{
    //二維數(shù)組
    int a[3][4] = {0};
 
    printf("%d\n",sizeof(a)); // 48 
    printf("%d\n",sizeof(a[0][0])); // 4
    printf("%d\n",sizeof(a[0])); // 16
    printf("%d\n",sizeof(a[0]+1)); // 4/8
    printf("%d\n",sizeof(*(a[0]+1)));// 4
    printf("%d\n",sizeof(a+1)); // 4/8
    printf("%d\n",sizeof(*(a+1))); // 16
    printf("%d\n",sizeof(&a[0]+1)); // 4/8
    printf("%d\n",sizeof(*(&a[0]+1))); // 16
    printf("%d\n",sizeof(*a)); // 16
    printf("%d\n",sizeof(a[3])); // 16
 
    return 0;
}

 sizeof(a)

這里的a表示的是整個數(shù)組,所以大小為4*(3*4)=48。

sizeof(a[0][0])

a[0][0]表示第一行第一列的元素,由于數(shù)組是int型,所以一個元素的字節(jié)大小為4.

sizeof(a[0])

a[0]表示第一行的數(shù)組名,a[0]作為數(shù)組名單獨放在sizeof內(nèi)部,計算的是整個數(shù)組大小,即第一行的大小,4*4=16。

sizeof(a[0]+1)

這里的a[0]作為第一行的數(shù)組名,沒有&,沒有單獨放在sizeof內(nèi)部,所以a[0]表示的就是首元素的地址,即a[0][0]的地址,a[0]+1就是第一行第二個元素的地址,是地址就是4/8。

sizeof (*(a[0]+1))

a[0]+1就是第一行第二個元素的地址,對其解引用,就是第一行第二個元素,大小為4。

sizeof(a+1)

a是二維數(shù)組的數(shù)組名,是類型為 int(*)[4] 的數(shù)組指針,沒有&,沒有單獨存放在sizeof內(nèi)部,a表示首元素的地址,即第一行的地址,a+1就是第二行地址,是地址,大小就為4/8個字節(jié)。

sizeof (*(a+1))

(a+1)就是第二行元素的地址,解引用就是第二行的數(shù)組名,計算的是第二行的大小,所以大小為16個字節(jié)。( *(a+1) --> a[1] )

sizeof(&a[0]+1)

a[0]是第一行,&a[0]是地址,&a[0]+1就是第二行的地址,是地址大小就為4/8字節(jié)。

sizeof (*(&a[0]+1))

對第二行的地址解引用,也就是a[1],大小為16字節(jié)。

sizeof(*a)

a是二維數(shù)組的數(shù)組名,沒有&,沒有單獨放在sizeof內(nèi)部,a表示首元素地址,*a就是二維數(shù)組的首元素,也就是第一行,大小為16字節(jié)。( *a --> *(a+0) --> a[0] )

sizeof(a[3])

a[3]看起來是越界了,但是計算的時候它會去推導要計算的類型,例如:

int a=10; sizeof(int)和 sizeof(a)計算的大小一樣,它會去推導a的類型是int型。同理,它也會去推導a[3]的類型,a[3]的類型是 int [4],所以大小為16。 

通過上面的一些講解,接下來我們看一些實戰(zhàn)題:

指針筆試題 

筆試題1

#include<stdio.h>
int main()
{
  int a[5] = { 1, 2, 3, 4, 5 };
  int *ptr = (int *)(&a + 1);
  printf( "%d,%d", *(a + 1), *(ptr - 1));
  return 0;
}
//程序的結(jié)果是什么?

講解 :

 如圖,a是數(shù)組名,也就是首元素的地址,a+1就是第二個元素的地址,對(a+1)解引用就是第二個元素2,打印出來2; 

ptr是一個指針,指向的是數(shù)組的末尾,且被強制轉(zhuǎn)換成int *類型,所以ptr-1跳過的是一個int,對其解引用就是數(shù)組的最后一個元素5。

筆試題2

#include<stdio.h>
struct Test
{
    int Num;
    char *pcName;
    short sDate;
    char cha[2];
    short sBa[4];
}*p;
 
//假設p 的值為0x100000。 如下表表達式的值分別為多少?
//已知,結(jié)構(gòu)體Test類型的變量大小是20個字節(jié)
 
int main()
{
    p = (struct Test*)0x100000;
    printf("%p\n", p + 0x1);
    printf("%p\n", (unsigned long)p + 0x1);
    printf("%p\n", (unsigned int*)p + 0x1);
    return 0;
}

講解:

已知這里的p是一個結(jié)構(gòu)體指針,p+0x1就相當于結(jié)構(gòu)體指針+1,而這個結(jié)構(gòu)體類型的變量大小是20個字節(jié),也就是加了20個字節(jié),化為十六進制為0x100014;

(unsigned long) p把p強制轉(zhuǎn)換成unsigned long型,這里的p就相當于是一個無符號類型的數(shù),內(nèi)存里面就默認為存的就是一個普普通通的整形數(shù)字,整型數(shù)字加1就是加1,所以結(jié)果為0x100001;

(unsigned int *)p把p強制轉(zhuǎn)換成unsigned int *,這里的p就是整型指針,而整型指針加1就是加4個字節(jié),所以結(jié)果為0x100004。

筆試題3

#include<stdio.h>
int main()
{
  int a[4] = { 1, 2, 3, 4 };
  int *ptr1 = (int *)(&a + 1);
  int *ptr2 = (int *)((int)a + 1);
  printf( "%x,%x", ptr1[-1], *ptr2);
  return 0;
}

如圖,ptr1就是&a+1,跳過整個數(shù)組,再強制轉(zhuǎn)換成int * 型,而ptr1[-1]相當于 *(ptr1-1),也就是跳過一個int * 型,所以ptr1[-1]==4,用%x打印出來也是4;

(int *)((int)a + 1),a是首元素地址,強轉(zhuǎn)換為int型,也就是把這個地址看成普普通通的整型數(shù)字,一個整型數(shù)字加1就是簡簡單單的加1,是地址這個數(shù)字+1,而不是地址+1,所以跳過的是一個字節(jié)。而我們知道數(shù)據(jù)在內(nèi)存中的存儲分大小端,這里我們以小端為例,如圖ptr2指向的是一個整型中的第二個字節(jié),從第二個字節(jié)開始取出一個整型,以小端輸出,所以結(jié)果為02000000。

筆試題4

#include <stdio.h>
int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    int *p;
    p = a[0];
    printf( "%d", p[0]);
    return 0;
}

講解:

這里要看清楚題目,數(shù)組里面的是圓括號,所以是逗號表達式,數(shù)組其實就是

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

p = a[0] 即p指向的是數(shù)組的第一行,p[0]就是數(shù)組第一行一個元素,所以打印出來是1。

筆試題5

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

這里p是一個數(shù)組指針,p指向的數(shù)組是4個元素,而a是一個5行5列的數(shù)組,如下圖:

好了,今天就講到這里!這些是否讓你對數(shù)組和指針有了新的看法呢?

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

相關文章

  • 詳解C語言中for循環(huán)與while循環(huán)的用法

    詳解C語言中for循環(huán)與while循環(huán)的用法

    這篇文章主要通過幾個示例為大家介紹一下C語言中for循環(huán)與while循環(huán)的用法以及二者的區(qū)別,文中的代碼講解詳細,對我們學習C語言有一定幫助,需要的可以參考一下
    2022-07-07
  • 一起來了解c語言的str函數(shù)

    一起來了解c語言的str函數(shù)

    這篇文章主要為大家詳細介紹了c語言的str函數(shù),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • C語言一看就懂的選擇與循環(huán)語句及函數(shù)介紹

    C語言一看就懂的選擇與循環(huán)語句及函數(shù)介紹

    函數(shù)是一個功能模塊,它把實現(xiàn)某個功能的代碼塊包含起來,并起一個函數(shù)名,供別人調(diào)用,如printf函數(shù),如system函數(shù)。是程序運行當中包裝起來的一個步驟;選擇與循環(huán)是編程中最常用的結(jié)構(gòu),本篇文章用最簡單的文字帶你了解它們
    2022-04-04
  • Cocos2d-x學習筆記之開發(fā)環(huán)境搭建

    Cocos2d-x學習筆記之開發(fā)環(huán)境搭建

    這篇文章主要介紹了Cocos2d-x學習筆記之開發(fā)環(huán)境搭建,本文使用Visual Studio作為開發(fā)IDE,是不同于其它教程的,需要的朋友可以參考下
    2014-09-09
  • 解決了個困擾了2天的問題,定點運算問題

    解決了個困擾了2天的問題,定點運算問題

    本文主要講解定點運算問題,需要的朋友可以參考一下。
    2016-06-06
  • Eclipse對printf()不能輸出到控制臺的快速解決方法

    Eclipse對printf()不能輸出到控制臺的快速解決方法

    Eclipse對printf()不能輸出到控制臺的快速解決方法。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-10-10
  • C語言開發(fā)實現(xiàn)貪吃蛇游戲

    C語言開發(fā)實現(xiàn)貪吃蛇游戲

    這篇文章主要為大家詳細介紹了C語言開發(fā)實現(xiàn)貪吃蛇游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • C語言學習之指針的使用詳解

    C語言學習之指針的使用詳解

    想突破C語言的學習,對指針的掌握是非常重要的,本文為大家總結(jié)了C語言中指針的相關知識點,文中的示例代碼講解詳細,感興趣的小伙伴可以學習一下
    2022-10-10
  • C++實現(xiàn)控制臺版掃雷程序

    C++實現(xiàn)控制臺版掃雷程序

    這篇文章主要為大家詳細介紹了C++實現(xiàn)控制臺版掃雷程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C 語言結(jié)構(gòu)體的使用方法

    C 語言結(jié)構(gòu)體的使用方法

    這篇文章主要介紹了C 語言結(jié)構(gòu)體的使用,文章介紹了結(jié)構(gòu)體定義的多種類型,想具體了解的朋友請看下面文章的內(nèi)容
    2021-09-09

最新評論