C語言陣列與指標(Arrays and Pointers)關係解析-差不多是一回事兒
C語言陣列與指標(Arrays and Pointers)
A pointer to a given data type can store the address of any variable of that particular data type. For example, in the following code, the pointer variable pc
stores the address of the character variable c
.
char c = 'A';
char *pc = &c;
Here, c
is a scalar variable that can store only a single value.
However, you are already familiar with arrays that can hold multiple values of the same data type in a contiguously allocated memory block.
So, you might wonder, can we have pointers to arrays too? Indeed, we can.
Let us start with an example code and look at its output. We would discuss its behavior subsequently.
char vowels[] = {'A', 'E', 'I', 'O', 'U'};
char *pvowels = &vowels;
int i;
// Print the addresses
for (i = 0; i < 5; i++) {
printf("&vowels[%d]: %u, pvowels + %d: %u, vowels + %d: %u\n", i, &vowels[i], i, pvowels + i, i, vowels + i);
}
// Print the values
for (i = 0; i < 5; i++) {
printf("vowels[%d]: %c, *(pvowels + %d): %c, *(vowels + %d): %c\n", i, vowels[i], i, *(pvowels + i), i, *(vowels + i));
}
A typical output of the above code is shown below
&vowels[0]: 4287605531, pvowels + 0: 4287605531, vowels + 0: 4287605531
&vowels[1]: 4287605532, pvowels + 1: 4287605532, vowels + 1: 4287605532
&vowels[2]: 4287605533, pvowels + 2: 4287605533, vowels + 2: 4287605533
&vowels[3]: 4287605534, pvowels + 3: 4287605534, vowels + 3: 4287605534
&vowels[4]: 4287605535, pvowels + 4: 4287605535, vowels + 4: 4287605535
vowels[0]: A, *(pvowels + 0): A, *(vowels + 0): A
vowels[1]: E, *(pvowels + 1): E, *(vowels + 1): E
vowels[2]: I, *(pvowels + 2): I, *(vowels + 2): I
vowels[3]: O, *(pvowels + 3): O, *(vowels + 3): O
vowels[4]: U, *(pvowels + 4): U, *(vowels + 4): U
&vowels[i]
= pvowels + i
= vowels + i
vowels[i]
= *(pvowels + i)
= *(vowels + i)
This is because the name of an array itself is a (constant) pointer to the first element of the array. In other words, the notations vowels
, &vowels[0]
, and vowels + 0
all point to the same location.
Pointers And Arrays
In C there is a very close connection between pointers and arrays. In fact they are more or less one and the same thing! When you declare an array as:int a[10];
you are in fact declaring a pointer a to the first element in the array. That is, a is exactly the same as &a[0]. The only difference between a and a pointer variable is that the array name is a constant pointer - you cannot change the location it points at. When you write an expression such as a[i] this is converted into a pointer expression that gives the value of the appropriate element. To be more precise, a[i] is exactly equivalent to *(a+i) i.e. the value pointed at by a + i . In the same way *(a+ 1) is the same as a[1] and so on.
Being able to add one to a pointer to get the next element of an array is a nice idea, but it does raise the question of what it means to add 'one' to a pointer. For example, in most implementations an int takes two memory locations and a float takes four. So if you declare an int array and add one to a pointer to it, then in fact the pointer will move on by two memory locations. However, if you declare a float array and add one to a pointer to it then the pointer has to move on by four memory locations. In other words, adding one to a pointer moves it on by an amount of storage depending on the type it is a pointer to.
This is, of course, precisely why you have to declare the type that the pointer is to point at! Only by knowing that a is a pointer to int and b is a pointer to float can the compiler figure out that
a + 1
means move the pointer on by two memory locations i.e. add 2, and
b + 1
means move the pointer on by four memory locations i.e. add 4. In practice you don't have to worry about how much storage a pointer's base type takes up. All you do need to remember is that pointer arithmetic works in units of the data type that the pointer points at. Notice that you can even use ++ and -- with a pointer, but not with an array name because this is a constant pointer and cannot be changed. So to summarise:
- An array's name is a constant pointer to the first element in the array that is a==&a[0] and *a==a[0].
- Array indexing is equivalent to pointer arithmetic - that is a+i=&a[i] and *(a+i)==a[i].
It is up to you whether you want to think about an array as an array or an area of storage associated with a constant pointer. The view of it as an array is the more sophisticated and the further away from the underlying way that the machine works. The view as a pointer and pointer arithmetic is more primitive and closer to the hardware. In most cases the distinction is irrelevant and purely a matter of taste.
One final point connected with both arrays and functions is that when you pass an entire array to a function then by default you pass a pointer. This allows you to write functions that process entire arrays without having to pass every single value stored in the array - just a pointer to the first element. However, it also temps you to write some very strange code unless you keep a clear head. Try the following - write a function that will fill an array with random values randdat(a,n) where a is the array and n is its size. Your first attempt might be something like:
void randdat(int *pa , int n)
{
for (pa = 0 ; pa < (n-1) ; pa++ ) *pa = rand()%n + 1;
}
Well I hope your first attempt wouldn't be like this because it is wrong on a number of counts! The problem is that the idea of a pointer and the idea of an index have been confused. The pointer pa is supposed to point to the first element of the array, but the for loop sets it to zero and then increments it though a series of memory locations nowhere near the array. A lesser error is to suppose that n-1 is the correct final value of the array pointer! As before, you will be lucky if this program doesn't crash the system, let alone itself! The correct way of doing the job is to use a for loop to step from 0 to n-1, but to use pointer arithmetic to access the correct array element:
int randdat(int *pa , int n)
{
int i;
for ( i=0 ; i$$$$ n ; ++i)
{
*pa = rand()%n + 1;
++pa;
}}
Notice the way that the for loop looks just like the standard way of stepping through an array. If you want to make it look even more like indexing an array using a for loop you could write:
for(i=0 ; i$$$$n ; ++i) *(pa+i)=rand()%n+1;
or even:
for(i=0 ; i$$$$n ; ++i) pa[i]=rand()%n+1;
In other words, as long as you define pa as a pointer you can use array indexing notation with it and it looks as if you have actually passed an array. You can even declare a pointer variable using the notation:
int pa[];
that is, as an array with no size information. In this way the illusion of passing an array to a function is complete.
相關文章
- C語言 指標與陣列C語言指標陣列
- C語言指標(三):陣列指標和字串指標C語言指標陣列字串
- c語言-運算子,陣列,指標C語言陣列指標
- C指標和陣列的關係詳解指標陣列
- C語言指標和陣列筆試題C語言指標陣列筆試
- (C語言)使用指標列印陣列的內容C語言指標陣列
- 指標陣列與陣列指標指標陣列
- C語言系列之 指標與陣列總複習視訊教程C語言指標陣列
- 指標陣列和陣列指標與二維陣列指標陣列
- C++語言程式設計筆記 - 第6章 - 陣列、指標與字串C++程式設計筆記陣列指標字串
- c程式設計--指標與陣列C程式程式設計指標陣列
- C陣列和指標陣列指標
- C語言指標C語言指標
- C語言陣列C語言陣列
- 陣列指標,指標陣列陣列指標
- C語言使用指標對陣列指定位置進行插入元素C語言指標陣列
- c語言字元陣列C語言字元陣列
- c語言的陣列C語言陣列
- C語言學習之:指標與字串C語言指標字串
- Go 陣列指標(指向陣列的指標)Go陣列指標
- 二維陣列與指標陣列指標
- c語言指標彙總C語言指標
- C語言指標用法大全C語言指標
- C語言 函式指標C語言函式指標
- C語言指標筆記C語言指標筆記
- C語言基礎-指標C語言指標
- C語言指標學習C語言指標
- C語言指標(二) 指標變數 ----by xhxhC語言指標變數
- c語言關於陣列的簡單運算C語言陣列
- C語言知識彙總 | 51-C語言字串指標(指向字串的指標)C語言字串指標
- C語言知識彙總 | 56-C語言NULL空指標以及void指標C語言Null指標
- 陣列指標陣列指標
- C語言指標詳解(一)C語言指標
- C語言指標詳解(二)C語言指標
- C語言基礎-1、指標C語言指標
- c語言實現this指標效果C語言指標
- 搞清楚C語言指標C語言指標
- C語言指標基本知識C語言指標