2013-08-06 36 views
1

我得到,當你聲明一個數組,如:概念上,爲什麼數組地址不可修改?

int Numbers[5]; 
int *intPtr = NULL; 

你不能做到以下幾點:

Numbers++; 
Numbers + 1 = intPtr; 
Numbers = NULL; 
etc 

什麼是對的製造基地地址(以及隨後的地址)的動機數組常量(?或不可改變的)讓我們說一些奇怪的原因,我想這樣做:

Numbers + 8 = intPtr; 

爲什麼不編譯器讓過去的人訪問定位的整數(在這種情況下是5)?

+3

這裏有兩個不同的問題,第二個與第一個問題無關。而且,它的實現是這樣的,因爲否則就沒有意義了。 – 2013-08-06 12:21:15

+4

這就好比問我是否給我的第一個孩子命名爲'比爾',爲什麼我不能把他的名字帶回去給我的第二個孩子,讓第一個孩子沒有名字?技術上可行,但不是這樣一個好主意。 – AShelly

+1

Numbers是一個數組。增加數組的意義是什麼? –

回答

1

數字是一個名字......它的類型是int [5]。 Number ++在這裏意味着什麼?它是去數字[1]還是超越數字[5]?從這個意義上說,它不是很清楚。同樣,Numbers = NULL是什麼意思?這是否意味着一個隱含的空間分配給數組Numbers [5]?這可能不是一種c語言標準的答覆......但只是一種直觀的感覺。

1

編譯器不會允許你這樣做。因此,如果你這樣做,你將失去陣列的所有5個元素。 也數字是一個變量。你不能改變變量的地址。您可以更改其中的值。

1

首先我們來談談什麼標準說:6.3.2.1/3 「其他操作數/左值,數組和功能標示符」:

Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue.

現在爲何不可修改的?

因爲如前所述它是指向數組的初始元素,所以對這個指針的任何改變都會導致原始數組的損失。我們可以在這個地址的副本上進行遞增和遞減以訪問此數組的元素。

最後一個問題:

什麼是你想找到了結合array.You的已提出過這樣得到了空間5種元素[0] [4]。訪問[5]並不安全,因爲它不是爲您保留的,因此可能導致分段錯誤或數據損壞。

+0

「因爲如前所述它是指向數組的初始元素的指針」不,它不是。數組表達式是一個數組表達式。它可以*轉換成*在特定上下文中的指針表達式*。 – newacct

+0

@newacct同意了,但我剛剛談到了數組名稱,它是指向它的第一個元素的指針。在數組名稱上增加一個增量就是_certain context_你正在談論的內容。如果我錯了,請糾正我。 –

1

您不能更改Numbers的值,因爲Numbers不是左值。如果你嘗試類似Numbers++的東西,編譯器會抱怨你試圖分配一些不是左值的東西。

Numbers不是左值的原因是它是數組的名稱。如果更改Numbers的值,則無法引用數組,從而導致數組無意義。你可以,但是,使Numbers值的拷貝和修改,如:

int numbers[5]; 
int *n = (int*)malloc(sizeof(int) * 5); 
printf("numbers is: %p\n", n); 
n++;       // this is OK 
printf("numbers is: %p\n", n); 

注意n是一個指針,而numbers不是指針而是數組。

+0

「數字不是左值的原因是它是數組的名稱。」我不認爲這可以解釋任何事情。 C可以使它成爲一個左值,這樣如果你爲它分配了另一個'int [5]'數組,它將所有元素複製到這個數組中,並且數組的位置不會改變。 (事實上​​,當數組是一個結構體的成員並且你指定了這個結構體時,會發生這種情況。)不支持的事實是語言設計的選擇。 – newacct

5

int Numbers[5]; 

您還沒有定義指針的情況。你正在定義一個數組。實際上,Numbers的類型是int[5]。而你正在定義的那個數組,它在某個地方有一個內存位置。該存儲器的基地(int *)Numbers指出。由於內存不能移動到任何地方,移動(int *)Numbers也是非法的。

並注意,這種不變性的內存位置不限於數組。例如:

int x; 

現在,您將如何在內存中移動x?如果你做x++,那會增加x,但它不會移動它。並試圖做任何數學與x指針肯定不會在內存中移動xx(或Numbers)在內存中的位置在創建x時設置,無論您嘗試多麼努力,都無法移動它。這適用於任何類型的–,您不能移動一個整數,也不能移動數組。

+0

'(&x)'不是左值,你不能增加它,'(&x)++'不應該編譯,與'5 ++'類似。 –

+0

@PaulGriffiths - 謝謝。這應該是顯而易見的;我只是沒有想到。我修好了它。 – JoshG79

+0

「請注意,內存位置的這種不變性不侷限於陣列。」但是,不可分配性對於數組類型是唯一的。 – newacct

1

你不能做這樣的事情:

Numbers + 8 = intPtr; 

有任何變量,沒關係的數組。也許你的意思是這樣,這是合法的,這兩個指針和數組:

int main(void) { 
    int array[5]; 
    int * p; 

    p = array; 

    *(p + 3) = 4;  /* works */ 
    *(array + 4) = 5; /* also works */ 

    return 0; 
} 

爲什麼你會想嘗試的int *的價值分配到的int有5個元素的數組是9號元素但是,超越了我。

1

你不能這樣做的原因是因爲這可能會破壞(進程)內存。因此,如果我們分配「int Numbers [5]」,那麼這將保留5個整數的連續記憶。當你超越這個5個整數的區域時,你正在訪問一個沒有分配給數組的內存區域 - 這個區域可能被其他變量使用。

如果你的數組需要額外的空間,那麼你可以使用動態數組或鏈表。使用動態數組,可以創建一個新數組,將所有元素複製到新存儲中,然後釋放舊數組。通過鏈接列表,我們爲列表中的每個節點分配一個新的內存區域。然後,使用next(或prev)指針,我們使它指向列表中其他節點的內存位置。但是,在這兩種情況下,我們都不會超越分配給我們的記憶。