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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

指针和数组分析

發(fā)布時間:2025/4/5 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 指针和数组分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 1 數(shù)組的訪問方式
      • 1 數(shù)組的訪問方式
    • 2 指針和數(shù)組名的不同
      • 2.1 指針和數(shù)組名的不同
    • 3 數(shù)組作為函數(shù)參數(shù)
      • 3.1 數(shù)組參數(shù)退化的意義
      • 3.2 一維數(shù)組作為函數(shù)參數(shù)
      • 3.3 二維數(shù)組作為函數(shù)參數(shù)
    • 4 數(shù)組指針和指針數(shù)組
      • 4.1 數(shù)組指針
      • 4.2 指針數(shù)組
    • 5 指針和數(shù)組的糾纏

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

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

我們首先來看一個問題,數(shù)組名可以當作常量指針使用,那么指針是否也可以當作數(shù)組名來使用呢?

數(shù)組可以以下標的形式和以指針的形式兩種方式進行訪問:


下標形式VS指針形式:

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

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

示例代碼:

#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; }

2 指針和數(shù)組名的不同

2.1 指針和數(shù)組名的不同

雖然我們可以通過指針訪問數(shù)組,但是我們必須知道數(shù)組名和指針僅使用方式相同:

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

看如下代碼:

// main.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; }// extern.c a[] = {1, 2, 3, 4, 5};/* 分析:當編譯器編譯到extern int* a;這句話話的時候就會把a這個標識符當作一個指針看待。指針a的地址為就 是數(shù)組a標識符所在的地址,&a就是a所在的地址值,a就是里面保存的值(0x1),*a就是保存的地址值所對應的內存中 的值,因此會產(chǎn)生段錯誤。*/

3 數(shù)組作為函數(shù)參數(shù)

3.1 數(shù)組參數(shù)退化的意義

首先我們要知道C語言中只會以值拷貝的方式進行參數(shù)傳遞。
當我們向函數(shù)傳遞數(shù)組時,其實有如下兩種實現(xiàn)方案:

  • 將整個數(shù)組拷貝一份傳入函數(shù)。
  • 將數(shù)組名看作常量指針傳數(shù)組首元素地址。
  • C語言選擇的是第二種方式,是因為C語言以高效作為最初設計目標:

    • 參數(shù)傳遞的時候如果拷貝整個數(shù)組執(zhí)行效率將大大下降。
    • 參數(shù)位于棧上,太大的數(shù)組拷貝將導致棧溢出。

    3.2 一維數(shù)組作為函數(shù)參數(shù)

    當一位數(shù)組作為函數(shù)參數(shù)時,編譯器將其編譯成對應的指針。

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

    3.3 二維數(shù)組作為函數(shù)參數(shù)

    二維數(shù)組同樣存在退化的問題:

    • 二維數(shù)組可以看作是一維數(shù)組。
    • 二維數(shù)組中的每個元素是一維數(shù)組。

    二維數(shù)組參數(shù)中第一維的參數(shù)可以省略:

    • void f(int a[5]) <--> void f(int a[]) <--> void f(int* a)
    • void f(int a[3][3]) <--> void f(int a[][3]) <--> void f(int(*a)[3])

    二維數(shù)組并不是退化為二級指針,而是退化為數(shù)組指針!指針數(shù)組才是退化為二級指針!

    記住如下表格!!!

    關于數(shù)組作為參數(shù),還需要注意以下幾點:

    • C語言無法向一個函數(shù)傳遞任意的多維數(shù)組,對于多維數(shù)組的函數(shù)參數(shù)只有第一維是可變的。
    • 必須提供除第一維之外的所有維長度
      • 第一維之外的維度信息用于完成指針運算。
      • N維數(shù)組的本質是一維數(shù)組,元素是N-1維的數(shù)組。
      • 對于多維數(shù)組的函數(shù)參數(shù)只有第一維是可變的。

    傳遞與訪問二維數(shù)組:

    #include <stdio.h>void access(int a[][3], int row) {int col = sizeof(*a) / sizeof(int);int i = 0;int j = 0;printf("sizeof(a) = %d\n", sizeof(a)); // 4printf("sizeof(*a) = %d\n", sizeof(*a)); // 12for(i=0; i<row; i++){for(j=0; j<col; j++){printf("%d\n", a[i][j]);}}printf("\n"); }void access_ex(int b[][2][3], int n) {int i = 0;int j = 0;int k = 0;printf("sizeof(b) = %d\n", sizeof(b)); // 4printf("sizeof(*b) = %d\n", sizeof(*b)); // 24for(i=0; i<n; i++){for(j=0; j<2; j++){for(k=0; k<3; k++){printf("%d\n", b[i][j][k]);}}}printf("\n"); }int main() {int a[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};int aa[2][2] = {0};int b[1][2][3] = {0};access(a, 3);access(aa, 2); // compile warningaccess_ex(b, 1);access_ex(aa, 2); // compile warningreturn 0; }

    4 數(shù)組指針和指針數(shù)組

    4.1 數(shù)組指針

    先來看下數(shù)組類型:

    • C語言中的數(shù)組有自己特定的類型。
    • 數(shù)組的類型由元素類型和數(shù)組大小共同決定。比如,int array[5]的類型為int[5]。

    定義數(shù)組類型:

    • C語言中通過typedef為數(shù)組類型重命名,typedef type(name)[size]。
    • 數(shù)組類型:
      • typedef int(AINT5)[5];
      • typedef float(AFLOAT10)[10];
    • 數(shù)組定義:
      • AINT5 iArray;
      • AFLOAT10 fArray;

    數(shù)組指針:

    • 數(shù)組指針用于指向一個數(shù)組。
    • 數(shù)組名是數(shù)組首元素的起始地址,但并不是數(shù)組的起始地址。
    • 通過將取地址符&作用于數(shù)組名可以得到數(shù)組的起始地址。
    • 可通過數(shù)組類型定義數(shù)組指針:ArrayType* pointer;。
    • 也可以直接定義:type(*pointer)[n];
      • pointer為數(shù)組指針變量名。
      • type為指向的數(shù)組的元素類型。
      • n為指向的數(shù)組的大小。

    4.2 指針數(shù)組

    指針數(shù)組:

    • 指針數(shù)組是一個普通的數(shù)組。
    • 指針數(shù)組中每個元素為一個指針。
    • 指針數(shù)組的定義:type* pArray[n];

      指針數(shù)組的應用:
    #include <stdio.h> #include <string.h>#define DIM(a) (sizeof(a)/sizeof(*a))int lookup_keyword(const char* key, const char* table[], const int size) {int ret = -1;int i = 0;for(i=0; i<size; i++){if( strcmp(key, table[i]) == 0 ){ret = i;break;}}return ret; }int main() {const char* keyword[] = {"do","for","if","register","return","switch","while","case","static"};printf("%d\n", lookup_keyword("return", keyword, DIM(keyword)));printf("%d\n", lookup_keyword("main", keyword, DIM(keyword)));return 0; }

    5 指針和數(shù)組的糾纏

    有時候還是會分不清指針和數(shù)組名之間的關系,主要是二維數(shù)組,一維數(shù)組倒是沒什么問題。懶得寫太多,就直接拿代碼測試下,如下:

    // CodeTest.cpp : 定義控制臺應用程序的入口點。 //#include "stdafx.h" #include <iostream> #include <windows.h>using namespace std;int main() {/****************************一維數(shù)組************************************/int array1[5] = { 1, 2, 3, 4, 5 };// 當數(shù)組名放在sizeof中代表的是整個數(shù)組cout << sizeof(array1) << endl; //20// 當數(shù)組名直接做右值時,其代表數(shù)組空間中第一個元素的地址int* p1 = array1;//int* p11 = &array1; //注意:&array1的類型是int (*)[5],數(shù)組指針cout << p1 << endl; //0x003DF998cout << &array1 << endl; //0x003DF998cout << p1[1] << endl; //其本質也是簡單的指針運算 + 解引用cout << array1[1] << endl; //其本質也是簡單的指針運算 + 解引用cout << *(p1 + 1) << endl; //簡單的指針運算cout << "------------------" << endl;/****************************二維數(shù)組************************************/int array2[3][3] = {{ 1, 2, 3 },{ 4, 5, 6 },{ 7, 8, 9 }};// 當數(shù)組名放在sizeof中代表的是整個數(shù)組cout << sizeof(array2) << endl; //36// 當數(shù)組名直接做右值時,其代表數(shù)組空間中第一個元素的地址int (*p2)[3] = array2; //二維數(shù)組也可以看成是一維的,不過每一維都是一個一維數(shù)組//所以其數(shù)組空間的第一個元素的地址就是指向一維數(shù)組的//int (*p22)[3] = &array2; //&array2的類型是int (*)[3][3]cout << (*p2)[0] << endl; //*p2得到其所指向的一維數(shù)組的第一個元素的指針cout << *(*p2 + 0) << endl;cout << (*array2)[0] << endl; //[]有兩個作用:1.指針運算 2.解引用//*array2 得到二維數(shù)組中第一個元素(也就是一個一維數(shù)組)中//的第一個int類型元素的地址,然后通過[]運算符進行地址偏移//和解引用然后得到第一個int類型元素的值cout << *array2[0] << endl; //array2[0]得到第一個元素(也就是一個一維數(shù)組)中第一個int類型//的地址值,然后再通過*拿到其中存儲的值//其實array2、&array2、*array2的地址值都是一樣的,只是其類型不同而已,需要注意。system("pause");return 0; }

    參考資料:

  • C語言進階剖析教程
  • 總結

    以上是生活随笔為你收集整理的指针和数组分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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