[C++]C++小筆記 ----- 函數

1. 函數創建

In C++, 創建函數分爲三個步驟:

  1. 函數聲明 / function prototyping, function prototyping is not optional in C++. prototyping happens during compile time and is termed as "static type checking". It helps to check errors that are hard to find during run-time; 
  2. 函數定義;
  3. 調用函數;
例子:

#include <iostream>
using namespace std;

//1. function prototype.
void simple();

int main() {
	cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
	//3. call functions.
	simple();
	return 0;
}

/*
 * 2. function definition.
 */
void simple() {
}

1. 函數聲明

爲什麼要有函數聲明呢? 

  1. 函數聲明向編譯器描述了函數接口, 即, return type and number & type of parameters. 當一個有返回值的函數結束運算的時候,調用這個函數的函數,也許是main()需要從CPU寄存器/內存中讀取這個返回值。因爲函數聲明指定了返回值的類型,所以compilers知道how many bytes to read and how to intercept them.
  2. 編譯器可以確保程序員使用了正確的參數數目, 類型, 以及 return type.

函數聲明帶參數時,參數類型可以不帶參數名。

int cal(int); 
int cal(int value);

如果聲明中帶參數名,函數定義時的參數名可以與聲明時的參數名不同。

Leaving the parentheses empty is the same as using the keyword "void" in the parentheses.

int cal(); == int cal(void);


2. 函數參數

C++ normally passes arguments by value. That means
int cal(double side);

The value of variable side  is passed to function cal(). A copy of side's value is stored in cal() and cal() works with the copy of "side"  rather than with its original value. 


Parameters and variables declared inside a function are private to the function. They are calledLocal Variables.When a function is called, the computer allocates memory for these local variables. When a function terminates, the computer frees the memory that are used by those variables automatically. 

1. 函數參數與數組

當數組被用來當作參數傳遞給函數時,數組是作爲指針傳遞到函數中去的, 數組將自己的地址傳給了函數。
所以, 下面的使用方法是可以的。

#include <iostream>
using namespace std;

//function prototype.
int simple(int arr[], int size);
int complex(int * arr, int size);

int main() {
	cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
	const int size = 8;
	int cookies[size] = { 1, 2, 3, 4, 5, 6, 7, 8 };
        const int * px = &size;
	cout<<"The size of cookies "<<sizeof(cookies)<<endl;
	cout<<cookies<<" = The address of cookies"<<endl;
        cout<<"The size of px "<<sizeof(px)<<endl;
	//call functions.
	double temp = simple(cookies, size);
	cout << "total is " << temp << endl;

	temp = complex(cookies, 3);
	cout<<"The first 3 eaters ate ";
	cout<<temp<<endl;


	temp = complex(cookies + 5, 3);
	cout<<"The last 3 eaters ate ";
	cout<<temp<<endl;

	return 0;
}

int complex(int * arr, int size) {
	double total;
	total = 0;

	cout<<"The size of complex cookies "<<sizeof(arr)<<endl;
	cout<<arr<<" = The address of complex cookies"<<endl;

	for (int i = 0; i < size; i++) {
		total += arr[i];
	}
	return total;
}

/*
 * function definition.
 */
int simple(int arr[], int size) {
	double total;
	total = 0;
	cout<<"The size of simple cookies "<<sizeof(arr)<<endl;
	cout<<arr<<" = The address of simple cookies"<<endl;

	for (int i = 0; i < size; i++) {
		total += arr[i];
	}
	return total;
}

結果。

The size of cookies 32
The size of px 8
0x7fff57c72840 = The address of cookies
The size of simple cookies 8
0x7fff57c72840 = The address of simple cookies
total is 36
The size of complex cookies 8
0x7fff57c72840 = The address of complex cookies
The first 3 eaters ate 6
The size of complex cookies 8
0x7fff57c72854 = The address of complex cookies
The last 3 eaters ate 21

從結果來看,cookies是數組和指針時, 它的地址是一樣的。但是他們的sizeof()不同,sizeof(Type Array) reutrns the size of the whole array, while the sizeof(pointer-to-int) only returns the size of the pointer. 所以,在方法中我們不用sizeof()傳來的array來計算數組的size.


因爲數組是作爲指針傳遞給函數的, 所以函數是直接在original array上操作,而不是在copy上。如果想讓函數無法修改數組的值,可以使用keyword 
const.

void show_array(const double ar[], int n);

This indicates that ponter 'ar' points to const double values. However, This does not means that the original array needs to be constant, it just means that you cannot alter the content of array 'ar' in function 'show_array()'.

int show_array(const double ar[],int size);

int main() {
	double ar[2] = {1,2};
	show_array(ar, 2);
	return 0;
}

int show_array(const double ar[], int limit) {
	for( int i = 0; i < limit; i++) {
		cout<<ar[i] <<" ";
	}
	cout<<endl;
}

'ar' is an array whose contents are const doubles. 

const double ar[] == const double *ar;

'ar' is a pointer that ponits to const double values.

2. 函數參數---數組的長度

我們之前通過一個證書來指定數組的長度。其實我們也可以通過ranges的方式來指定數組的長度。

int * pt = new int[2];

pt指向長度爲2的數組。pt指向第一個元素,pt+1指向第二個。pt+2指向數組結尾後的元素。Thus,

int * pe = pt+2;

double array_ranges(const double *begin, const double *end);

int main() {
	double ar[2] = {1,2};

	double temp = array_ranges(ar, ar+2);
	cout<<" total is "<< temp<<endl;
        return 0;
}

double array_ranges(const double *begin, const double * end) {
	double total = 0;
	const double * member;
	for(member = begin; member!=end; member++) {
		total += *member;
	}
	return total;
}

數組的首個元素的地址被傳遞到函數中。


3. 函數和二維數組

int data[3][4] = {{1,2,3,4}, {9,8,7,6}, {2,4,6,8}};
int total = sum(data, 3);

data is a pointer-points-to-array-of-4-int. so the appropriate way to define it is.

int total(int (*arr)[4], int size);

(*arr) means arr is an pointer. The int means arr points to an int arry with size of 4.

An alternative format that means exactly the same thing but easier to read is

int sum(int arr[][4], int size);
Either way, arr is a pointer.
int sum(int arr[][4], int size)
{
int total = 0;
for (int r = 0; r < size; r++)
for (int c = 0; c < 4; c++)
total += arr[r][c];
return total;
}


4. 函數與struct

struct與其他基本類型一樣,在C++中是值傳遞。struct也可以用指針傳遞。基本上有兩個方式。
1. struct變量是指針,
void test(structX *);   //prototype.

structX *m = new structX(...);
test(m);


2.struct變量是object。
void test(structX *);

structX m = {....};
test(&m);

函數與函數指針

函數指針分爲三步:
  1. obtaining the address of a function;
    1. The name of a function is a pointer to that function's address in memory of the machine code.
    2. The pointer to a function should also acts like a pointer to the address of that function.
  2. Declare the pointer to a function;
    1. a function pointer need to specify the return value and parameter of the function.
int function1(int);   //function prototype.
int (*fp)(int);  //declare a function pointer.
fp = function1;

() have higher rank than *, so
*fp(int)  //A function pt with parameter type int and return a pointer.
(*fp)(int) //A function pointer pt with parameter type int.
  1. Use Function pointers
int x = (*fp)(10);

C++ also allow 
int y = fp(10);

Because of the second point in "obtaining the address of a function;"

Array of function pointers.

以下參個函數
const double * (*f1)(const double ar[], int x);
const double * (*f2)(const double [], int);
const double* (*f3)(const double *, int);

其實擁有相同的參數列表。因爲
1. const double ar[] == const double * ar;
2. const double [] == const double ar[];          //function prototype can omit the identifiers.

So, 
const double * (*pa)(const double *, int);   //is a function pointer.

也可以在聲明的時候同時賦值。
const double * (*pa)(const double *, int) = f1;
OR
auto pa = f1;

Array of function pointers.

Array of X pointers
const double * (*pa[3])(const double * , int ) = {f1, f2, f3};

[] has higher rank than *, so *pa[3] is an array of three pointers. each of which  is a pointer to a function that takes a const double * and int as arguments and return a const double *.

We can also do
auto pb = pa;
because the name of an array is the pointer to the first element of the array. so both of pa and pb 
are pointers to a pointer to a function. both pa[0] and pb[0] are pointers to function. so
const double * px = pa[0](av, 3); 
OR
cosnt double * py= (*pa[0])(av, 3);

Pointer to an array of function pointers.

*pd[3];           // array of three pointers.
(*pd)[3];        // pa is a pointer which points to array of three elements.
To combine above two togather,
const double *  (* /*pointer-to-*/ (*pd[3])/* array of three pointers*/)(const double *, int) = &pa;

Thus, pd points to an array, then *pd is the array of function pointers. (*pd)[i] is an array element, which is a pointer to a function.
To call a function,
(*pd)[i](av, 3);    //function pointer
OR
*(*pd)[i](av, 3);   //actual function address

注: 數組pa 和&pa也許有相同的數值,但是他們是不同的類型。
pa as the name of the array is also the address of the first element of the array 
pa==&pa[0];

&pa is the address of the entire array. 例如: pa + 1指向&pa[1], &pa+1指向整個數組結尾後與數組相同大小的內存空間。

*pa == pa[0] == **&pa;

Simplify with typedef

As we recal, 
typedef double real;   //makes real as another name for double

typedef const double* (*pf)(const double *, int);

pf is now a type name.

pf p1 = f1;

p1 points to the f1() function.

Then
pf pa[3] = {f1, f2, f3};  // pa array of 3 function pointers.
pf (*ppf)[3] = &pa;     //ppf points to an array of 3 function pointers.



 






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章