數組訪問形式
『壹』 訪問數組中的某個元素可以通過什麼來完成
與使用下標相比,使用指針能使C編譯程序更容易地產生優質的代碼。假設你的程序中有這樣一段代碼:
/* X la some type */
X a[MAX];
X *p; /*pointer*/
X x; /*element*/
int i; /*index*/
為了歷數組a中的所有元素,你可以採用這樣一種循環方式(方式a)
/*version (a)*/
for (i = 0; i<MAX; ++i)
{
x=a[i];
/* do something with x * /
}
你也可以採用這樣一種循環方式(方式b)
/*veraion(b)*/
for (p = a; p<&a[MAX]; ++p )
{
x=*p;
/* do aomething with x * /
}
這兩種方式有什麼區別呢?兩種方式中的初始情況和遞增運算是相同的,作為循環條件的比較表達式也是相同的(下文中將進一步討論這一點)。區別在於「x=a[]」和「x=*p」,前者要確定a[i]的地址,因此需要將i和類型x的大小相乘後再與數組a中第一個元素的地址相加;
後者只需間接引用指針p。間接引用是快速的,而乘法運算卻比較慢。
這是一種「微效率」現象,它可能對程序的總體效率有影響,也可能沒有影響。對方式a來說,如果循環體中的操作是將數組中的元素相加,或者只是移動數組中的元素,那麼每次循環中大部分時間就消耗在使用數組下標上;如果循環體中的操作是某種I/O操作,或者是函數調用,那麼使用數組下標所消耗的時間是微不足道的。
在有些情況下,乘法運算的開銷會降低。例如,當類型x的大小為1時,經過優化就可以將乘法運算省去(一個值乘以1仍然等於這個值);當類型x的大小是2的冪時(此時類型x通常是系統固有類型),乘法運算就可以被優化為左移位運算(就象一個十進制的數乘以10一樣)。
在方式b中,每次循環都要計算&a[MAX],這需要多大代價呢?這和每次計算a[i]的代價相同嗎?答案是不同,因為在循環過程中&a[MAX]是不變的。任何一種合格的編譯程序都只會在循環開始時計算一次&a[MAX],而在以後的每次循環中重復使用這次計算所得的值。
在編譯程序確認在循環過程中a和MAX都不變的前提下,方式b和以下代碼的效果是相同的:
/* how the compiler implements version (b) */
X *temp = &a[MAX]; /* optimization */
for (p = a; p< temp; ++p )
{
x =*p;
/*do something with x * /
}
遍歷數組元素還可以有另外兩種方式,即以遞減而不是遞增的順序遍歷數組元素。對按順序列印數組元素這樣的任務來說,後兩種方式沒有什麼優勢,但是對數組元素相加這樣的任務來說,後兩種方式比前兩種方式更好。通過下標並且以遞減順序遍歷數組元素的方式(方式c)如下所示(人們通常認為將一個值和。比較的代價要比將一個值和一個非零值比較的代價小:
/* version (c) */
for (i = MAX - 1; i>=0; --i)
{
x=a[i];
/* do aomcthing with x * /
}
通過指針並以遞減順序遍歷數組元素的方式(方式d)如下所示,其中作為循環條件的比較表達式顯得很簡潔:
/* version (d) */
for (p = &a[MAX - 1]; p>=a; --p )
{
x =*P;
/*do something with x * /
}
與方式d類似的代碼是很常見的,但不是絕對正確的,因為循環結束的條件是p小於a,而這有時是不可能的(見9.3)。
通常人們會認為「任何合格的能優化代碼的編譯程序都會為這4種方式產生相同的代碼」,但實際上許多編譯程序都沒能做到這一點。筆者曾編寫過一個測試程序(其中類型x的大小不是2的冪,循環體中的操作是一些無關緊要的操作),並用4種差別很大的編譯程序編譯這個程序,結果發現方式b總是比方式a快得多,有時要快兩倍,可見使用指針和使用下標的效果是有很大差別的(有一點是一致的,即4種編譯程序都對&a[MAX]進行了前文提到過的優化)。
那麼在遍歷數組元素時,以遞減順序進行和以遞增順序進行有什麼不同呢?對於其中的兩種編譯程序,方式c和方式d的速度基本上和方式a相同,而方式b明顯是最快的(可能是因為其比較操作的代價較小,但是否可以認為以遞減順序進行要比以遞增順序進行慢一些呢?);對於其中的另外兩種編譯程序,方式c的速度和方式a基本相同(使用下標要慢一些),但方式d的速度比方式b要稍快一些。
總而言之,在編寫一個可移植性好、效率高的程序時,為了遍歷數組元素,使用指針比使用下標能使程序獲得更快的速度;在使用指針時,應該採用方式b,盡管方式d一般也能工作,但編譯程序為方式d產生的代碼可能會慢一些。
需要補充的是,上述技巧只是一種細微的優化,因為通常都是循環體中的操作消耗了大部分運行時間,許多C程序員往往會舍本求末,忽視這種實際情況,希望你不要犯相同的錯誤。
『貳』 使用數組名訪問數組元素和使用指針變數訪問數組元素有和不同
指針是可以隨意移動的,而數組名不行,比如說定義一個
int a[4]={11,22,33,44};int *p=a;要訪問其中的第二個元素,用數組名只能
用*(a+1)的方式,a不能自加或自減,而指針p則可以p++後,訪問*p,也可以
*(p+1)的方式。
『叄』 對數組元素的訪問有幾種形式簡述其優缺點。
你可以單個元素的賦值例如 a[1]=10;
也可以所有元素一起初始化 a[10]={1,2,3,4,5,6,7,8,9,10};
也可以聲明指針訪問 *(a+1) 等價於 a[1] *(a+2)=a[2]; ......
暫時想到這些 - -
有什麼不懂可以追問
『肆』 指針與數組是如何訪問的——可以用extern int *p作為int p[N]的外部聲明嗎
[摘要]C語言中,很多情況下指針與數組的的使用方式十分類似,使用數組名為一個指針變數賦值也是完全合法的。這造成一個假象,即數組就是指針,對
於它們二者的區別是一個老生常談的話題,本文僅從指針與數組訪問內存的方式進行區分,其餘不再贅述。另外還討論了使用指針作為數組的外部聲明時產生的問
題,以及extern int a[]與extern int a[N]的一點小區別。
1、數組與指針訪問內存的方式數組訪問:指針訪問指針偏移訪問:可見,
指針訪問內存的方式更為靈活,但它會增加一次額外的內存讀取
,即先將指針的值從內存中讀出來,再用它作為地址去訪問數據。
2、使用指針作為數組的外部聲明
例如以下代碼:[cpp]view plainfile2.cintp[100];……file1.cexternint*p;……p[0]=1;
根據指針訪問內存的方式,編譯器首先提取p的值,在VC 6.0編譯環境下,此處提取的是0x0000 0000,然後加上偏移量18CH,將1寫入,程序崩潰。修正方法:使聲明與定義相匹配
,聲明為extern int p[];
3、數組聲明中要不要寫明元素個數
聲明並不分配內存,只是告訴編譯器對象的名字和類型,所以一般不需寫明數組大小,但對於多維數組要寫明左邊一維之外的其他維的長度——給編譯器足夠的信息去產生代碼。
但是,如果在引用變數處需要使用sizeof來取得數組大小,則必須指明,因為編譯時編譯器會計算出sizeof的結果。經試驗,此處sizeof的結果只與聲明中指定的元素個數相關,與定義處無關。
在上例中,如果按以下方式聲明:[cpp]view plainexternintp[];//1externintp[100];//2externintp[50];//3
三者中sizeof(p)的結果分別是
『伍』 數組遍歷常見的方式有
數組遍歷常見的方式有:
一、forEach方法
forEach是最簡單、最常用的數組遍歷方法,它提供一個回調函數,可用於處理數組的每一個元素,默認沒有返回值。
二、map方法
map,從字面上理解,是映射,即數組元素的映射。它提供一個回調函數,參數依次為處於當前循環的元素、該元素下標、數組本身,三者均可選。默認返回一個數組,這個新數組的每一個元素都是原數組元素執行了回調函數之後的返回值。
map方法不改變原數組。
三、filter方法
filter,過濾,即對數組元素的一個條件篩選。它提供一個回調函數,參數依次為處於當前循環的元素、該元素下標、數組本身,三者均可選。默認返回一個數組,原數組的元素執行了回調函數之後返回值若為true,則會將這個元素放入返回的數組中。
filter方法不改變原數組。
四、some、every方法
some方法和every的用法非常類似,提供一個回調函數,參數依次為處於當前循環的元素、該元素下標、數組本身,三者均可選。
數組的每一個元素都會執行回調函數,當返回值全部為true時,every方法會返回true,只要有一個為false,every方法返回false。當有一個為true時,some方法返回true,當全部為false時,every方法返回false。
some、every方法不改變原數組。
五、rece方法
rece方法有兩個參數,第一個參數是一個回調函數(必須),第二個參數是初始值(可選)。回調函數有四個參數,依次為本輪循環的累計值、當前循環的元素(必須),該元素的下標(可選),數組本身(可選)。
rece方法,會讓數組的每一個元素都執行一次回調函數,並將上一次循環時回調函數的返回值作為下一次循環的初始值,最後將這個結果返回。
如果沒有初始值,則rece會將數組的第一個元素作為循環開始的初始值,第二個元素開始執行回調函數。
最常用、最簡單的場景,是數組元素的累加、累乘。
rece方法不改變原數組。
六、for of方法
es6新增了interator介面的概念,目的是對於所有數據結構提供一種統一的訪問機制,這種訪問機制就是for of。
即:所有有interator介面的數據,都能用for of遍歷。常見的包括數組、類數組、Set、Map等都有interator介面。
(5)數組訪問形式擴展閱讀:
數組(Array)是有序的元素序列。若將有限個類型相同的變數的集合命名,那麼這個名稱為數組名。組成數組的各個變數稱為數組的分量,也稱為數組的元素,有時也稱為下標變數。用於區分數組的各個元素的數字編號稱為下標。數組是在程序設計中,為了處理方便, 把具有相同類型的若干元素按有序的形式組織起來的一種形式。 這些有序排列的同類數據元素的集合稱為數組。
數組是用於儲存多個相同類型數據的集合。
在C語言中, 數組屬於構造數據類型。一個數組可以分解為多個數組元素,這些數組元素可以是基本數據類型或是構造類型。因此按數組元素的類型不同,數組又可分為數值數組、字元數組、指針數組、結構數組等各種類別。
『陸』 怎麼訪問數組中的數據
使用for循環語句+文件操作函數即可文件中數據讀取並存到數組中。
1、C語言標准庫提供了一系列文件操作函數。文件操作函數一般以f+單詞的形式來命名(f是file的簡寫),其聲明位於stdio.h頭文件當中。例如:fopen、fclose函數用於文件打開與關閉;fscanf、fgets函數用於文件讀取;fprintf、fputs函數用於文件寫入;ftell、fseek函數用於文件操作位置的獲取與設置。一般的C語言教程都有文件操作一章,可以找本教材進一步學習。
2、常式:
#include<stdio.h>
int i,a[100];
int main(){
FILE * fp1 = fopen("input.txt", "r");//打開輸入文件
FILE * fp2 = fopen("output.txt", "w");//打開輸出文件
if (fp1==NULL || fp2==NULL) {//若打開文件失敗則退出
puts("不能打開文件!");
rturn 0;
}
for(i=0;fscanf(fp1,"%d",a+i)!=EOF;i++);//從輸入文件連續讀取整數到數組a
for(;i--;)fscanf(fp2,"%d ",a[i]);//把數組a逆序寫入到輸出文件當中
fclose(fp1);//關閉輸入文件
fclose(fp2);//關閉輸出文件,相當於保存
return 0;
}
『柒』 匯編數組中的訪問形式有幾種呢能否舉例參考一下
一維數組ARRAY ARRAY[SI] 首址ARRAY+偏移量[SI]
二維數組ARRAY ARRAY[SI][BX] 首址ARRAY+橫向偏移[SI]+縱向偏移[BX]
『捌』 如何訪問數組中的元素
具體步驟如下:
1、用list來演示,安裝好python與pycharm之後,打開pycharm,新建Test_List.py。
『玖』 php 中對數組訪問的幾種方式
主要有兩種方式,一是for循環遍歷,二四foreach遍歷;
for循環主要通過循環嵌套實現遍歷,
foreach和遍歷一維數組差不多啦,主要是輸出有差別.
如果我的回答沒能幫助您,請繼續追問。
您也可以向我們團隊發出請求,會有更專業的人來為您解答。