總網頁瀏覽量

2013年5月11日 星期六

C語言回顧

C語言沒有string
但是C++有不過string似乎非C語言的關鍵字

#include<stdio.h>
以#開頭的指令在程式編譯前會由前處理器先行處理。

cout << "ByeByeWorld" << endl;
//相當於printf("ByeByeWorld\n");
將ByeByeWorld輸出到顯示器上,並將指標cursor移到下一行
這種訊息叫做提示prompt

endl 表面上是換行字元
事實上是指示CPU將記憶體中的資料送到輸出資料流中(ex:顯示器 或某檔案)

cin >> variable;
//相當於scanf("%d",&variable);


C語言的if-else跟java有點不一樣
if(name=1)可以編譯過且可以執行


函數:
分三部分函數宣告、函數定義、函數呼叫

void main(){
editdistance(num);

return 0;
}

int editdistance(int n){
int x;
return x;
}


傳直呼叫:editdiatance函數被呼叫時,引數num先複製到記憶體的stack區塊,接著將n放進stack,接收num的值,進行運算完之後return x;將x複製一份到stack之內,最後main再將stack的結果複製回來。


reference參照:
int N =5;
int& M=N;
M是N的參照,alias
有點像java的 String str ="kkk";  String str2=str;
M變數成為N的綽號
更改M會改變N
更改N會改變M
參照宣告時要初始化否則會發出警告

應用:swap function

傳參照使用時機如果不是以下三種狀況最好不要用,避免無意間更改變數值
1.傳遞過去的引數必須改變
2.傳回兩個以上的值
3.有大量數值需要傳遞,如果採用傳直呼叫,將耗費大量時間在數值複製上
例如引數為大量陣列的情況


陣列:
一維陣列:vector
二維陣列:matrix
三維陣列:tensor

陣列宣告事先宣告大小
const int SIZE =5;
double Pressure[SIZE];
陣列名稱Pressure內存陣列起始位置
可以直接function(Pressure);
傳遞參數呼叫function,function使用的陣列跟main使用的陣列是同一個而不是複本
這是傳址呼叫,在function所做的更動作用在原本陣列身上

sizeof(變數);回傳變數所占記憶體大小
其實是變數實際所站的空間與一個char所占空間比值

陣列大小必須在編譯階段就可以確定的整數
不可以宣告成以下這樣
int a=9;
float farr[a];

指標:


double A = 2.5;
double* pF; //宣告pF,變數型態為"指向double變數的指標型態"
pF= &A;//pF儲存A的記憶體位置,指標pF指向變數A
cout<<*pF<<endl;
//印出pF指向的變數內容


注意double*的指標不可以指向int變數
(編譯器不會自動convert)
也就是說double限制住指標可以指向那些型態變數

記住double* pF;
pF資料型態是double*


double x;
x =*pF;
將pF指向的變數內容存到x裡面


*以及&在宣告時候的意義是告知變數型態而不是取址取值運算
double* p;
double &y=x;

陣列指標:
一個指標存放陣列的位置(也等於array[0]的位置)。


const int size =5;
double V[size]={55.66,11.22,33.44,77.88,99.11};
double* pv=V;
//pv存放陣列的位置
int i=0;
for(i=0;i<size;i++){
cout<< *(pv+i)<<endl;
//指標加1等於陣列位移一格
}

V本身就是一個指標,存放陣列的位置
所以for loop也可以寫
*(V+i)也OK啦



二維陣列的指標
利用指標存取二維陣列:
指標的指標

double B[Row][Col]= {{1.8,4.9,6.8},{6.2,4.1,6.3}};
*B表示存取B[0]也就是陣列B的位置
*B+1同等於*(B+1)先加再取,存取B[1]的元素
**B表示存取B[0][0]的位置
**(B+1)存取B[1][0]同等於*(*(B+1))


int i,j;
for(i=0;i<Row;i++){
for(j=0;j<Col;j++)
{

cout << *(*(B+i)+j) << endl;

}

}

指標參數(傳址呼叫)

X=func(&x,&y);
int func(int*  x, int*  y)

回憶:傳參照呼叫
X=func(a,b)
int func(int& x,int& y)
一旦設定指向參考的變數之後,這個參考就無法再指向其他的變數


6.指標未設定初值不可以這樣寫

int *ptr;
*ptr=2;
//會compile error

7.
可以直接將字串存進指標變數
char* ptr="118";
cout<< ptr;//直接印出字串

int x=112;
 int* num=112;//錯誤寫法,只有字串才可以這樣用
cout<< num;

8.
C++的NULL要大寫,NULL是常數定義為 ((void*)0)


9.不論指標指向哪種資料型別記憶體空間
,指標變數大小一律為4bytes  。


10.指標為何要宣告資料型別?
因為程式要透過指標變數所宣告的資料型別,判斷指標所指向的變數是哪種類型。
這樣編譯器可以知道指標的索引增減該移動多少位元
例如:double指標變數指向double 陣列。當變數+1時候邊義器就知道要移動八位元組才會得到下一筆double資料。


所以指向不同型別變數的指標變數不可以互相指派
int x=19;
double* ptr =&x;
這樣ptr往下一筆存資料index會移動八位元組
而int只有四個位元組
ptr存到第三筆資料去了

11.
可以透過強制型別轉換:讓double* 指標變數可以指向int*指標變數

int i=10;
int* ptr_i=&i;
double* ptr_d;
ptr_d=(double*)ptr_i;

cout<<"ptr_i ="<< ptr_i <<endl;
cout<<"*ptr_i="<<*ptr_i<<endl;

cout<<"ptr_d ="<< ptr_d <<endl;
cout<<"*ptr_d="<<*ptr_d<<endl;//印出奇怪的浮點數字   因為編譯器用8bytes解析
cout<<"*((int*)ptr_d)"<< *((int*)ptr_d)<<endl;//印出正確的數字  因為編譯器用4bytes 解析


12.
不定型别指標變數宣告void *
當宣告指標變數時,還不確定指標所指向的記憶體空間,將儲存哪種資料型別時候,可以將它宣告為
不定型別的指標void*


13.不定型別指標變數的強制轉換

int i=10;
int* ptr_i=&i, *ptr_i1=NULL;
void* ptr_void;

ptr_void=ptr_i;//不定型別可以指向各類型別指標

ptr_i1=(int*)ptr_void;
//各類型別指標要指向不定型別必須強制轉型

cout<<&i<<endl;
cout<<ptr_void<<endl;
cout<<ptr_i<<endl;
cout<<ptr_i1<<endl;
//以上四個值都一樣,那三個指標都指向i了
cout<< *(int*)ptr_void<<endl;
//務必再次轉換因為電腦不記得剛剛有轉過型別,否則會錯誤




沒有留言:

張貼留言