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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人工智能 > pytorch >内容正文

pytorch

【C语言进阶深度学习记录】三十 二维数组与二维指针

發(fā)布時間:2023/12/10 pytorch 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C语言进阶深度学习记录】三十 二维数组与二维指针 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 1 二維指針(指向指針的指針)
    • 2 二維數(shù)組
    • 3 二維數(shù)組的類型
      • 3.2 如何動態(tài)申請二維數(shù)組
    • 4 總結

1 二維指針(指向指針的指針)

  • 指針的本質是變量
  • 指針的指針是保存指針變量的地址。如下面的代碼:

為什么需要指向指針的存在?還記得之前學習的過程中說的函數(shù)傳值調用和傳址調用么?當要在函數(shù)內(nèi)部修改傳進來參數(shù)變量的時候,需要傳址調用。

同理,如果傳進來的本來就是一個指針,想要修改該指針,那么就需要傳指向該指針的指針了。道理是一樣的。看下面的代碼就明白了:

  • 代碼34-1.c:函數(shù)reset為重新為某一段內(nèi)存分配一段內(nèi)存空間(可大可小)
#include <stdio.h> #include <malloc.h>/* 想要修改p指向的內(nèi)容,且p的地址也是會變的,就必須使用傳址調用。傳p的地址。就是雙指針 */ int reset(char** p, int old_size, int new_size){int ret = 1;int i = 0;int len = 0;char* pp = *p;char* pt = NULL;char* tmp = NULL;if((NULL!=p) && (new_size>0)){pt = (char*)malloc(new_size);tmp = pt;len = (old_size < new_size) ? old_size : new_size;for(i=0; i<len; i++){*tmp = *pp;tmp++;pp++; }free(*p);*p=pt;}else{ret = 0;}return ret; }int main(){char* p = (char*)malloc(5);printf("p = %p\n",p);if(reset(&p, 5, 8)){printf("reset p = %p\n",p);}else{printf("no reset!\n");}free(p);return 0; }
  • 編譯運行結果為:

p = 0x8833008
reset p = 0x8833018

分析:

上述代碼中reset函數(shù)是重新為一塊內(nèi)存分配另一個內(nèi)存空間。我們知道要分配另一塊空間的話,地址肯定是會變的,那么想要最終將原來的地址p改變,就需要進行傳址調用。因為p本來就是指針,所以需要傳指針的指針進入reset函數(shù)。在reset函數(shù)中,進行重新分配內(nèi)存空間并將原有的內(nèi)存空間中的值拷貝到新的內(nèi)存地址處。具體自己好好看一下reset函數(shù)就可以理解。

由運行可以看出:

  • 地址p確實改變了,說明傳址調用起了作用
  • 注意理解指向指針的指針的意義與用法。需要多琢磨。

2 二維數(shù)組

在C語言中,沒有二維數(shù)組的概念。它只是另一種形式的一維數(shù)組。

  • 二維數(shù)組在內(nèi)存中是以一維數(shù)組的形式排布
  • 二維數(shù)組的第一維是一維數(shù)組(注意,一維數(shù)組相當于一個常量指針,也就說二維數(shù)組的第一維是存的指針)
  • 二維數(shù)組的第二維是具體存的數(shù)值
  • 既然一維數(shù)組的數(shù)組名可以看成是常量指針,那么二維數(shù)組的數(shù)組名也同樣可以看成是常量指針
  • 結合上述四條看看下圖中的二維數(shù)組在內(nèi)存中的樣式:


結合下面的代碼來認識認識二維數(shù)組:

  • 代碼:34-2.c :
#include <stdio.h>void print_array(int a[], int size){printf("print_array:sizeof(array) = %d\n",sizeof(a));int i = 0;for(i=0; i<size; i++){printf("%d ",a[i]);}printf("\n"); } int main(){int a[3][3] = {{0,1,2},{3,4,5},{6,7,8}}; int* p = &a[0][0];int i=0,j=0;for(i=0; i<3; i++){for(j=0; j<3; j++){printf("%d, ", a[i][j]);}printf("\n");}printf("\n");for(i=0; i<3; i++){for(j=0; j<3; j++){printf("%d, ", *(*(a+i)+j));}printf("\n");}printf("a = %p, a+1 = %p\n",a,a+1);printf("&a = %p, &a+1 = %p\n",&a,&a+1);printf("p = %p, p+1 = %p\n",p,p+1);printf("\n");print_array(p,9);return 0; }
  • 編譯運行結果為:

分析:

  • 上述代碼并不是很難,所以不做詳細分析。只做以下幾點說明:
  • 可以像這樣訪問二維數(shù)組:*(*(a+i)+j) 。可以想這樣理解: 其中a+i 代表是一維數(shù)組的第i個元素(即指針),*(a+i)代表找到第i個一維數(shù)組的起始地址,*(a+i)+j 表示第i個一維數(shù)組中的第j個元素的地址。最終*(*(a+i)+j) 表示取出元素。可以參考上面的二維數(shù)組的內(nèi)存圖。

  • 由:a = 0xbfb71b00, a+1 = 0xbfb71b0c 知道:二維數(shù)組的名字a可以看成是一個常量指針,它的值為二維數(shù)組首元素(這個首元素相當于是一個一維數(shù)組)的地址值。a+1就直接跨過一個一維數(shù)組的長度(這里是12,三個int)。

  • 由:&a = 0xbfb71b00, &a+1 = 0xbfb71b24 知道: &a 代表整個數(shù)組的地址(這與一維數(shù)組很相似)。&a+1 就直接跨過整個數(shù)組的大小到數(shù)組末尾

  • 由print_array 函數(shù)的參數(shù)是一維數(shù)組知道,二維數(shù)組在內(nèi)存中排布是一維數(shù)組的形式。參考上圖。

  • 3 二維數(shù)組的類型

    • 之前學過以為數(shù)組的類型如下:

    int a[5] ==>>> a的類型為: int*

    • 二維數(shù)組的類型為:

    int a[2][5] ==>>> a的類型為:int(*)[5]

  • 二維數(shù)組名可以看做是指向數(shù)組的常量指針
  • 二維數(shù)組可以看成是一維數(shù)組中存的元素類型是一個同類型的一維數(shù)組
  • 3.2 如何動態(tài)申請二維數(shù)組

    從下面的代碼來學習如何動態(tài)申請二維數(shù)組(參考下面的二維數(shù)組的內(nèi)存模型就可以理解下面的代碼):

    • 代碼:34-3.c:
    #include <stdio.h> #include <malloc.h>int** malloc2d(int row, int col){int** ret = NULL;if(row>0 && col>0){ret = (int**)malloc(row*sizeof(int*)); //相當于申請一個一維數(shù)組,存的元素是指針int* p = (int*)malloc(row*col*sizeof(int));//相當于二維數(shù)組在內(nèi)存中的一維排布,指針p指向這個一維排布if(NULL!=p && NULL!=ret){int i = 0;for(i=0; i<row; i++){ret[i] = p + i*col; // ret[i]存的是一個個指針指向的數(shù)組,每個數(shù)組長度是col,可以參考下圖的二維數(shù)組內(nèi)存模型}}else{free(ret);free(p);ret = NULL;}}return ret; }void free2d(int** p){if(NULL != *p){free(*p);}free(p); } int main(){int** a = malloc2d(3,3);int i=0,j=0;for(i=0; i<3; i++){for(j=0; j<3; j++){printf("a[%d][%d] = %d,", i,j,a[i][j]);}printf("\n");} free2d(a);return 0; }
    • 編譯運行代碼如下:

    雖然上述的數(shù)組中的各個值都是0,但是我們要知道m(xù)alloc申請后的內(nèi)存中的值是不確定的,并不一定是0

    分析:

    • 上述代碼中的核心代碼已經(jīng)標注,多畫圖分析即可
    • 可以參考下面的二維數(shù)組的內(nèi)存模型圖進行分析:

    至此,就學會了如何動態(tài)的申請二維數(shù)組了。一位數(shù)組的動態(tài)申請比較簡單,之前的文章也有學習過。

    4 總結

    • C語言中只支持一維數(shù)組,所謂的二維數(shù)組在內(nèi)存中依然是以一維數(shù)組的形式排布
    • C語言中的數(shù)組大小,必須在編譯期就作為常數(shù)確定。(畢竟數(shù)組的大小是數(shù)組類型的一部分,類型都不確定好,如何編譯)
    • 二維數(shù)組就是一個一維數(shù)組存的元素是同類型的數(shù)組而已

    總結

    以上是生活随笔為你收集整理的【C语言进阶深度学习记录】三十 二维数组与二维指针的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。