printf 指针地址_c语言对指针的理解
先來講一下本人學指針的經歷:大一的時候剛接觸c語言對指針這東西真的是太迷了,感覺麻煩難懂不想其他語言一樣。但是搞懂以后就被指針的魅力吸引甚至喜歡上c語言。不多講,開始!(文章可能有些長,但放心全是基礎的東西,里面有實際的例子。)
理解變量的存儲
int main()
{
? ? int a = 4;
? ? printf("%d\n", a);
? ? printf("%p", a);
? ? return 0;
}
結果:
4
00000004
(1)int a;
c語言在內存的存儲是以棧的形式。在棧中先定義了一個變量a并在內存中開辟了大小為4個字節的空間。然后讓a指向這片空間。此時小寶貝就有了自己的空間了,就可以放東西了,耶!
(2)a=4;
此時將4的值賦就是將4存到a的那片空間中。
由以上代碼可知,第一個輸出的是存放的值,第二個輸出的是a空間的地址。
但是我們通常是不直接這樣給變量賦值,往往是手動輸入:
scanf("%d",&a);
用戶先輸入一個int型的值,&a先找到自己的那片空間(&是取地址符),然后經值轉化為二進制存入到這個空間里。(嘿嘿,一個寶藏就這樣存了進來)
找到寶藏的法寶——指針
既然有了自己的空間又有了值,那誰能知道我的地址來發現我的寶藏呢?哈哈,指針來了。
他來了,他來了,他真的來了,,,,,,,
首先要知道,指針指向的是地址,是地址,是地址!不要誤以為他指的的是變量的值。
指針變量的定義與賦值:
第一種形式:
int *p=&a;
第二種形式:
int *p;
p=&a;
int *p;這里要區分,int*是在一起的,代表指針類型,p指的是指針變量。
多級指針
指向指針的指針,有時人們也管它叫多維指針。既然指針變量是一個變量,指針變量能存變量的內存的地址。
像 int * 存 int 型變量的地址,char * 存 char 型的地址,那指針理所當然可以存指針變量的地址啊。
例如,int ** 存 int * 的地址,int *** 存 int ** 的地址。
這就是一個二級指針存一級指針的地址,三級指針存二級指針的地址,人們把這樣的過程叫指向指針的指針,但其實也就是一個上一級的指針存了下一級的指針的地址而已。
因此,像上面說的,你存了它的地址,你就是指向它,所以:
二級指針存一級指針的地址,那么可以說二級指針指向一級指針
三級指針存二級指針的地址,那么可以說二級指針指向一級指針
多級指針用處多多。
唉,怎么說呢,本人也是剛學c語言沒多久,能力也有限,只是有自己的理解,例子還是請大家去實踐。
指針的應用
1.作為參數的指針(指針變量作為函數參數):我們都知道在使用自定義函數時,每個自定義函數與主函數之間聯系都是通過值傳遞的形式,但是并不能通過在自定義函數中改變參數的值來改變主函數中參數的值。但是通過指針,就能在自定義函數中訪問主函數的變量了。
簡單的例子:
void ?fun(int *p);
int i=0;fun(&i)//因為自定義函數形參是指針,所以調用函數時傳入地址。
這樣在自定義的函數中就可以通過這個指針訪問外面這個i
看幾個代碼的例子:
(1)不能通過在自定義函數中改變參數的值來改變主函數中參數的值:
voidchange(intp){printf("%d\n",p);//接受的值為5p=6;//想要改變參數的值}intmain(){intp=5;change(p);printf("%d\n",p);return0;}結果:55//值并沒有發生改變
(2)利用指針后:
void change(int *p)
{
? ? printf("%d\n", *p);//接受的值為5
? ? *p= 6;//通過指針訪問值,把p的值改為6
}
int main()
{
? ? int p=5;
? ? change(&p);//傳入地址
? ? printf("%d\n", p);
? ? return 0;
}
結果:
5
6
//主函數的值發生改變
再看一個例子:利用自定義函數來比較三個數的大小
#include
//交換
void swap(int* p1, int* p2)
{
? ? int temp;
? ? temp = *p1;
? ? *p1 = *p2;
? ? *p2 = temp;
}
//compare
void compare(int* p1, int* p2, int* p3)//定義指針變量,利用指針和主函數中的變量聯系
{
? ? if (*p1 > * p2)swap(p1, p2);
? ? if (*p1> * p3)swap(p1, p3);
? ? if (*p2> * p3)swap(p2, p3);
}
int main()
{
? ? int* p1, * p2, * p3, a, b, c;
? ? scanf_s("%d,%d,%d", &a, &b, &c);
? ? p1 = &a;//指針變量接收地址
? ? p2 = &b;
? ? p3 = &c;
? ? compare(p1, p2, p3);//自定義函數指針接收的仍是地址
? ? printf("%d,%d,%d", a, b, c);
? ? return 0;
}
2.雙胞胎——指針還是數組?(用數組名做函數參數):
首先必須了解一個基本知識。
大家都知道一個數組有多個變量,那么如何訪問數組中的變量(那么多寶藏怎么找啊)。數組是一個連續的空間,只要將首元素的地址賦給指針,指針通過首元素的地址訪問到了數組的首元素,那么通過遍歷的方法不就訪問到了整個數組。(就像順騰摸瓜一樣)
賦值方式:
int *p;
p=&a[0];
//或者利用元素名:
int *p;
p=a;//a=&a[0]
先看下列偽代碼:
代碼一
void fun(int arr[],int n )
'''''''
''''''
int main()
int array[10]=,,,,
,,,,,,,
fun(array,10)
代碼二
void fun(int *arr,int n )
'''''''
''''''
int main()
int array[10]=,,,,
,,,,,,,
fun(array,10)
這兩個偽代碼是等價的,即數組名作為函數參數時可以當做是指針。
原理嘛,允許我偷下懶哈哈,況且比我講的明白,(接圖):
代碼實例:
逆序輸出數組中的數
void reversed(int a[], int n)//數組作為指針變量接收地址,int a[]等價于int *a
{
? ? int i, j, m = (n - 1) / 2,temp;
? ? for (i = 0; i <= m; i++)
? ? {
? ? ? ? j = n - 1 - i;//控制序列j
? ? ? ? temp = a[i];
? ? ? ? a[i] = a[j];
? ? ? ? a[j] = temp;
? ? }
? ? for (int i = 0; i < 5; i++)
? ? ? ? printf("%d\t", a[i]);//利用指針訪問元素
}
int main()
{
? ? int a[5];
? ? int n = 5;
? ? for(int i = 0; i < 5; i++)
? ? {
? ? ? ? scanf_s("%d,", &a[i]);
? ? }
? ? for (int i = 0; i < 5; i++)
? ? {
? ? ? ? printf("%d\t", a[i]);
? ? }printf("\n");
? ? reversed(a, n);//數組名作為地址對函數進行調用
}
比較數組中數字的大小
void compare(int a[],int len,int *min,int *max)
{
? ? ? ? int i;
? ? ? ? *min =*max=a[0];
? ? ? ? for (i = 1; i < len; i++)
? ? ? ? {
? ? ? ? ? ? ? ?*max = a[i] > *max ? a[i] : *max;
? ? ? ? ? ? ? ?*min = a[i] < *min ? a[i] : *min;
? ? ? ? }
}
int main()
{
? ? ? ? int a[] = {1,2,3,4546,7,3,2,1,89,334};
? ? ? ? int i;
? ? ? ? int len = sizeof(a) / sizeof(a[0]);//數組的長度
? ? ? ? int min, max;
? ? ? ? compare(a,len,&min,&max);
? ? ? ? printf("min=%d,max=%d", min, max);
? ? ? ? return 0;
}
3.二維數組元素的地址
首先要明白的一點就是二維數組其實就是一維數組。在普通的一維數組中(a[0]),用數組名a作為數組a[0]的地址,那么在二維數組中(a[3][4]),a[0],a[1],a[2]就表示數組第一個元素的地址。這個結合一下實例可能比較好理解一下
代碼實例
以a[0]作為元素地址
int main()
{
? ? int a[3][4] = {12,2,3,4,56,7,8,9,10,1,9,34};
? ? //int n = 5;
? ? int* p;
? ? for(p=a[0]; p
? ? {
? ? ? ? if ((p - a[1]) % 4 == 0)
? ? ? ? ? ?printf("\n");
? ? ? ? printf("%d\t", *p);
? ? }
? ? return 0;
}
結果:
12? ? ? 2? ? ? ?3? ? ? ?4
56? ? ? 7? ? ? ?8? ? ? ?9
10? ? ? 1? ? ? ?9? ? ? ?34
E:\vs\c++\h\Debug\h.exe (進程 12316)已退出,代碼為 0。
按任意鍵關閉此窗口. . .
若以a[1]作為元素地址
int main()
{
? ? int a[3][4] = {12,2,3,4,56,7,8,9,10,1,9,34};
? ? //int n = 5;
? ? int* p;
? ? for(p=a[1]; p
總結
以上是生活随笔為你收集整理的printf 指针地址_c语言对指针的理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab函数输出,优化求解器输出函数
- 下一篇: Requirements of pair