初始C语言中的指针(翁凯男神MOOC)
運算符 &
● scanf("%d",&i);
●獲得變量的地址,它的操作數必須是變量
● int i; printf("%x",&i);
Int i=;
printf("%p\n",&i);
● 地址的大小是否與int相同取決于編譯器
&不能取的地址
●&不能對沒有地址的東西取地址
●&(a+b)
●&(a++)
●&(++a)
int a[];
printf("%p\n",&a);
printf("%p\n",a);
printd("%p\n",&a[]);
指針
●就是保存地址的變量
int i;
int *p=&i;
●指針指向某一個變量,指針里存放那個變量的地址
指針變量
●變量的值是內存的值
●普通變量的值是實際的值
●指針變量的值具有實際值的變量的地址
作為參數的指針
● void f(int *p);
●在被調用的時候得到了某個變量的地址;
●int i=0;f(&i);
●在函數里面可以通過這個指針訪問外面的這個i
訪問那個地址上的變量*
● *是一個單目運算符,用來訪問指針的值所表示的地址上的變量
● 可以做右值也可以做左值
● int k=*p;
● *p = k+1;
指針應用場景
●交換兩個變量的值
void swap(int *pa.int*pb)
{
int t = *pa;
*pa=*pb;
*pb=t;
}
●函數返回多個值,某些值就只能通過指針返回
void minmax(int a[],int len,int *max,int *min); int main(int argc, char **argv)
{
int a[]={,,,,};
int min,max;
minmax(a,sizeof(a)/sizeof(a[]),&min,&max);
printf("min=%d,max=%d\n",min,max); return ;
}
void minmax(int a[],int len, int *max,int *min){
int i;
*min=*max=a[];
for(i=;i<len;i++){
if(a[i]<*min){
*min=a[i];
}
if(a[i]>*max){
*max=a[i];
}
}
}
●函數返回運算的狀態,結果通過指針返回
●常用的套路是讓函數返回特殊的不屬于有效范圍內的值來表示出錯:
● -1 或 0 (在文件操作會看到大量的例子)
●但是當任何數值都是有效的可能結果時,就得分開返回了
int divide(int a,int b ,int *result); int main(int argc, char **argv)
{
int a=;
int b=;
int c;
if(divide(a,b,&c)){
printf("%d\n%d\n%d\n",a,b,c);
} return ;
}
int divide(int a,int b,int *result)
{
int ret=;
if(b==)ret=;
else{
*result=a/b;
}
return ret;
}
●后續的語言(C++ Java)采用了異常機制來解決這個問題
指針最常見的錯誤
●定義了指針變量,還沒有指向任何變量,就開始使用指針
傳入函數的數組成了什么?
●函數參數表中的數組實際上是指針
●size of (a)==size of (int*)
●但是可以用 數組的運算符[]進行運算
數組參數
●以下四種函數原型是等價的
● int sum(int *ar,int n);
●int sum (int *,int);
●int sum (int ar[],int n);
●int sum (int [],int);
數組變量本身就是特殊的指針
●數組變量本身表達地址,所以
● int a[10]; int*p=a; //無需用&取地址
●但是數組的單元表達的是變量,需要用&取地址
●a == &a[0]
●[] 運算符可以對數組做,也可以對指針做
●p[0] <==> a[0]
● *運算符可以對指針做,也可以對數組做
● *a=25;
● 數組變量是const的指針,所以不能被賦值
● int a[] <==> int *const a =
指針與const
指針是const(指針指向那個變量,這個事實不能被改變)
●表示一旦得到了某個變量的地址,不能再指向其他變量
int *const q =&i; // q是const
*q = ; // OK
q++; //ERROR
所指的是const
●表示不能通過這個指針去修改那個變量(并不能使得那個變量成為const)
const int *p = &i;
*p=; // ERROR! (*p)是const
i=; // OK
p=&j; //OK
轉換
●總是可以把一個非const的值轉換成const的
void f(const int *x);
int a = ;
f(&a); //OK
const int b=a;
f(&b); //OK
b = a+1; //ERROR
●當要傳遞的參數的類型比地址大的時候,這是常用的手段:既要用比較少的字節數傳遞給參數,又能避免函數對外面的變量的修改
const數組
const int a[]={,,,,};
●數組變量已經是const的指針了,這里的const表明數組的每個單元都是const int
●所以必須通過初始化進行賦值
指針運算
●給一個指針加1表示要讓指針指向下一個變量
int a[];
int *p=a;
*(p+1)--->a[1]
●如果指針不是指向一片連續分配的空間,如數組,則這種運算沒有意義
指針計算
●給指針加,減一個整數(+,+=,-,-=)
●遞增遞減(++/--)
●兩個指針相減(地址的差除以sizeof( 類型))
*p++
●取出p所指的那個數據來,完事之后順便把p移動到下一個位置去
● *的優先級雖然高,但是沒有++高
●常用于數組類的連續空間操作
●在某些CPU上,這可以直接被翻譯成一條匯編指令
char ac[] = {,,,,,,-}; // -1不是有效數字
char *p=ac
while(*p != -){
printf("%d\n",*p++);
}
遍歷數組ac
0地址
●當然你的內存中有0地址,但是0地址通常是個不能隨便碰的地址
●所以你的指針不應該具有0值
●因此可以用0地址來表示特殊的事情:
●返回的指針是無效的
●指針沒有被真正初始化(先初始化為0)
●NULL是一個預定定義的符號,表示0地址
●有的編譯器不愿意你用0來表示0地址
指針的類型
●無論指向什么類型,所有的指針的大小都是一樣的,因為都是地址
●但是指向不同類型的指針是不能直接互相賦值的
●這是為了避免用錯指針
指針的類型轉換
●void* 表示不知道指向什么東西的指針
●指針類型亦可以轉換類型
●int *p = &i; void*q = (void*)p;
●這并沒有改變p所指的變量的類型,而是讓后人用不同的眼光通過p看它所指的變量
●我不再當你是int啦,我認為你就是一個void!
用指針來做什么
●需要傳入較大的數據時用作參數
●傳入數組后對數組做操作
●函數返回不止一個結果
●需要用函數修改不止一個變量
●動態申請內存時
malloc
●#include<stdlib.h>
●向malloc申請的空間的大小都是以字節為單位的
●返回的結果是void*,需要類型為自己需要的類型
●(int*)malloc(n*sizeof(int))
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int number;
int *a;
printf("輸入數量");
scanf("%d",&number);
a=(int*)malloc(number*sizeof(int));
for (i=;i<number;i++){
a[i]=i*i;
}
free(a);
return 0;
}
沒空間了?
●如果申請失敗則返回0,或者叫做NULL
void *p=0;
int cnt=;
while((p=malloc(**))){
cnt++;
free(p)
printf("分配了%d00MB的空間\n",cnt);
free()
●把申請得來的空間還給系統
●申請過來的空間,最終都要還
●混出來的,遲早都要還的
●只能還申請的空間的首地址
總結
以上是生活随笔為你收集整理的初始C语言中的指针(翁凯男神MOOC)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 印度什么依据认定拉那克山口为边界点?
- 下一篇: 当兵两年后专升本 升的本科都是什么学校?