電腦是由一堆晶體管(Transistor)組成,可以把transistor想像成開關,因為開關只有兩種狀態,開或是關,對應到0或是1,因此電腦裡面所有東西都是由0和1來表示
電腦是用2進位(binary)
電腦的世界裡,一切都是數字...
8 bit = 1 byte
3-bit binary number可以代表多少數字?
N-bit binary number可以代表
個數字
000->0 ~ 111->7
1 byte可以存多少數字?
4 byte 呢 ?
1byte用16進位來表示會需要幾位?
int x;
cout << sizeof(x) << " bytes" << endl;
cout << sizeof(int) << " bytes"<< endl;syntax: sizeof(variable), sizeof(type)
取得一個型別或變數在記憶體中佔用的位元組數(bytes)
int 能儲存 4byte 的資料
範圍是: -2^31~2^31 - 1
也就是 −2,147,483,648 ~ 2,147,483,647
long long 能儲存 8byte 的資料
範圍是: -2^63 ~ 2^63 - 1
overflow: 數值超過表示範圍,變成不可預期的值
#include <iostream>
using namespace std;
int main() {
int x = 42;
x = 1e10;
cout << x <<"\n";
return 0;
}#define ll long long
ll a = 5;
long long a = 6;unsigned long long a = 3;unsigned: 沒有正負號
會把加在int 前面會讓表示範圍變成
0 ~ 2^32 - 1
加在long long前面呢 ?
變數是存放在計算機的記憶體裡面
要存取記憶體上的資料,我們會需要資料在記憶體的位址
因此一個變數會有一個相對應的記憶體位址
#include <iostream>
using namespace std;
int main() {
int x = 42;
cout << "x 的值是: " << x << endl;
cout << "x 的記憶體位址是: ";
cout << &x << endl;
return 0;
}
記憶體位址通常使用16進位來表示
0x開頭表示後面是16進位
電腦眼中的變數,就是變數儲存的位址
有了位址,我們就可以更輕鬆的操作變數
指標可以想像成一個變數指向另外一個變數
一個變數如何可以指向另外一個變數?
透過將目標變數的記憶體位址存起來,我們就可以與該變數建立連結
myvar = 25;
foo = &myvar;
bar = myvar;Remark:
用&可以拿到變數在記憶體的位址
暫時叫他取值運算子
baz = *foo;可以存取foo儲存的變數
其實就是去memory把
對應位址的資料取出
Syntax: type *name;
int *number;
char *character;
double *decimals;
Remark:
自己驗證一下,指標size都一樣嗎?
int *p = 0;
int *q = nullptr;
int *r = NULL;
通常指標剛開始宣告時不會只向任何記憶體(變數)
需要代表我們的指標現在沒有指向任何東西
Remark: 初始化最好都指向nullptr
#include <iostream>
using namespace std;
int main ()
{
int firstvalue = 8, secondvalue = 9;
int *mypointer;
mypointer = &firstvalue;
*mypointer = 10;
mypointer = &secondvalue;
*mypointer = 20;
cout<<"firstvalue is "<<firstvalue<<'\n';
cout<<"secondvalue is "<<secondvalue<<'\n';
return 0;
}int myvar;
int *myptr;
myptr = &myvar;
int myvar;
int *myptr;
*myptr = &myvar;
int myvar;
int *myptr = &myvar;
✅
✅
❌
int myvar;
int *foo = &myvar;
int *bar = foo;✅
哪裡錯 ?
int *a;
*a = 5;a沒有指向任何記憶體,因此不能進行存取
code要補充...
void swap_by_ref(int &a, int &b) {
int tmp = a;
a = b;
b = tmp;
}
swap_by_ref(a, b);pass-by-value v.s. pass-by-reference
| 項目 | reference(參考) | pointer(指標) |
|---|---|---|
| 寫法 | int &a | int *a |
| 呼叫方式 | 直接傳變數 | 傳變數位址 |
| 是否可為空 | 不可為空(必須綁定) | 可為 nullptr |
| 存取語法 | 直接用變數名 | 需 * 解參考 |
| 與 swap 關係 | 都能改到呼叫端變數 | 都能改到呼叫端變數 |
array其實也是儲存位址,只是大小以及位置無法改變
int myarray[20];
int *mypointer;mypointer = myarray;
✅
myarray = mypointer;
❌
陣列:固定位置的指標
int *p = (int *)1;
cout << p << "\n";
p += 1;//p += 5;
cout << p <<"\n";
long long *q = (long long *)1;
cout << q << "\n";
q += 1;
cout << q <<"\n";Remark:
(new_type)expression可以轉換類型
e.g. char c; cout <<(int)c;
指標的加減是以指到的元素大小為單位
int main() {
int *x = (int*)1;
int *y = (int*)5;
cout << y - x << endl;
long long *z = (long long*)17;
cout << z - (long long*)1 << endl;
return 0;
}int arr[] = {1, 2, 3, 4, 5};
int i = 0;
cout << *(arr + i);a[4] = 0;
*(a + 4) = 0;
上面兩個其實等價
int arr[5];
int *p = arr;
for(int i = 0; i < 5; i++)
{
*p = i;
p++;
}
for(int *i = arr; i < arr + 5; i++)
{
cout << *i <<"\n";
}void f(int arr[], int n)
{
for(int i = 0; i < n; i++)
{
arr[i] += 2;
}
return;
}寫一個function,接受參數是array和一個pointer,要求回傳pointer所指向的元素
是array裡面的第幾個元素?
int main() {
int arr[5] = {1, 2, 6, 7, 8};
int *ptr = (arr + 3);
cout << f(arr, ptr) <<" ";
cout << arr[f(arr, ptr)]<<"\n";
cout << *ptr <<"\n";
return 0;
}以前 C 是沒有string的,那時候要輸出字串必須要定義字元的陣列
char f1[10];
f1[0] = 'h', f1[1] = 'i', f1[2] = '\0';
cout << f1 <<"\n";char *foo = "hello";
cout << foo <<"\n";
cout << *(foo+4) << " "
<< foo[4] <<"\n";
char a;
char *b;
char **c;
a = 'z';
b = &a;
c = &b;如何透過c拿到a變數的value ?
pointers也可以代表函數
用( )把函數名稱括起來並加上*以及接受的參數
int f(int x, int y)
{
return x + y;
}
int main() {
int (*g)(int, int) = f;
cout << g(2, 3) << "\n";
return 0;
}
pointers可以讓函數作為一種參數,使其可以傳到另外一個參數
int addition (int a, int b)
{ return (a+b); }
int subtraction (int a, int b)
{ return (a-b); }
pointers可以讓函數作為一種參數,使其可以傳到另外一個參數
int operation (int x, int y, int (*func)(int,int))
{
int g;
g = (*func)(x,y);
return (g);
}
int m;
m = operation (7, 5, addition);