day 1-1
測試環境:Linux 2.6.32-279.el6.x86_64
測試代碼:pointer.cpp
#include <stdio.h>
/**
* test code: pointer.cpp
* test environment: Linux 2.6.32-279.el6.x86_64
*
* 總結:
* 1. 所有變量在聲明時,系統都會爲其分配一個內存地址
* 2. 普通變量在內存中存放的是值
* 3. 指針變量在內存中存放的是該指針指向的內存地址
* 4. 指針變量的類型與指針變量所指向的內存空間存儲的數據類型無關,
* 使用者可以指定所需的類型去讀取這些數據
*/
int main()
{
// 聲明一個類型爲int的變量,且賦值爲 17777
int i = 17777;
// 聲明一個指針變量 ip,ip 指向的內存空間的數據類型爲int
// 指針變量存放的是其指向的內存地址,而不是值本身,此處 ip 存放的應該是變量 i 的地址
// &i表示取變量 i 所在的內存地址
int *ip = &i;
// 聲明一個類型爲int的變量,且取指針變量 ip 的值並賦值給iv
int iv = *ip;
// 聲明一個指針變量cp,(char*)表示需要按照char類型的讀取方式去讀取cp指向的內存空間(&i)中存儲的數據
// 此處按照char類型去讀取 &i 則會對 &i 原來的4個字節進行截斷,只讀取1個字節的長度
char *cp = (char*)&i;
printf("%p: i=%d\n", &i, i);
printf("%p: ip=%p\n", &ip, ip);
printf("%p: iv=%d\n", &iv, iv);
printf("%p: cp=%p, *cp=%c\n", &cp, cp, *cp);
return 0;
}
編譯 && 執行
g++ -g pointer.cpp -O0 -o pointer
./pointer
執行結果
調試過程
day 1-2
測試環境:Linux 2.6.32-279.el6.x86_64
測試代碼:swap.cpp
/**
* test code: swap.cpp
* test environment: Linux 2.6.32-279.el6.x86_64
* 總結:
* 1. 在調用函數傳參時,傳的是變量的拷貝,而不是原始的值
* 2. 在修改指針指向的內存空間存儲的數據時,應使用操作符*
* 3. 操作引用參數實際操作的是參數所引用的對象
*/
/**
* 傳進來的是main函數中變量a和b的值的拷貝 c1, c2
* 交換的也是值的拷貝,並沒有改變a和b內存空間中的數據,
* 所以此函數並不能交換a和b的值
*/
void swap1(char c1, char c2)
{
char tmp = c1;
c1 = c2;
c2 = tmp;
}
/**
* 傳進來的是main函數中變量a和b的內存地址的拷貝 cp1, cp2
* 交換的也是內存地址的拷貝,並沒有改變a和b內存空間中的數據,
* 所以此函數並不能交換a和b的值
*/
void swap2(char *cp1, char *cp2)
{
printf("in swap2: *cp1=%c, *cp2=%c\n", *cp1, *cp2);
char *tmp = cp1;
cp1 = cp2;
cp2 = tmp;
printf("out swap2: *cp1=%c, *cp2=%c\n", *cp1, *cp2);
}
/**
* 傳進來的是main函數中變量a和b的內存地址的拷貝 cp1, cp2
* 然後通過操作符*來更新內存地址中的數據,所以此函數可以成功交換a和b的值
*/
void swap3(char *cp1, char *cp2)
{
printf("in swap3: *cp1=%c, *cp2=%c\n", *cp1, *cp2);
// 取c1指向的內存空間中的數據賦值給臨時變量tmp
char tmp = *cp1;
// 取cp2指向的內存空間中的數據賦值到cp1指向的內存空間中,覆蓋原有數據
*cp1 = *cp2;
// 將tmp的值賦值到cp2指向的內存空間中,覆蓋原有數據
*cp2 = tmp;
printf("out swap3: *cp1=%c, *cp2=%c\n", *cp1, *cp2);
}
/**
* 傳進來的是main函數中變量a和b的引用cr1, cr2
* cr1, cr2直接操作的是其引用的對象,所以此函數可以成功交換a和b的值
*/
void swap4(char &cr1, char &cr2)
{
char tmp = cr1;
cr1 = cr2;
cr2 = tmp;
}
int main()
{
char a = 'A';
char b = 'B';
printf("origin: a=%c, b=%c\n\n", a, b);
swap1(a, b);
printf("swap1: a=%c, b=%c\n\n", a, b);
swap2(&a, &b);
printf("swap2: a=%c, b=%c\n\n", a, b);
swap3(&a, &b);
printf("swap3: a=%c, b=%c\n", a, b);
// 重置 a, b 爲swap3交換之前的原值
a = 'A';
b = 'B';
swap4(a, b);
printf("swap4: a=%c, b=%c\n", a, b);
return 0;
}
編譯 && 執行
g++ -g swap.cpp -O0 -o swap
./swap
執行結果:
掃盲:
[k&r第1章第8節] In C, all function arguments are passed “by value.” This means that the called function is given the values of its arguments in temporary variables rather than the originals.
意思就是說在c語言裏,所有的函數傳參都是通過值傳遞:調用函數的時候傳遞過去參數值都是存放在臨時變量中,而不是存放在原來的變量中。
所以在調用函數的時候,會根據參數列表創建相應的一些臨時變量,然後將參數的值拷貝一份到臨時變量中,也就是說被調用的函數不能直接修改主調函數中變量的值。
分析過程:
變量a和b的在內存中的情況:
swap1中各個變量在內存中的情況:
調用swap1(char c1, char c2)時,會產生和變量a, b對應的臨時變量c1, c2(注意觀察上圖,這兩個變量所佔的內存空間的地址明顯和a, b不一樣),然後系統會將a, b的值分別賦值給c1, c2,此時不管swap1中如何操作c1, c2,都不會影響main函數中的變量a, b的值。
-gdb調試過程:
swap2中各個變量在內存中的情況:
在調用swap2(char *cp1, char *cp2)時,會產生對應的兩個臨時指針變量cp1, cp2,然後系統會將&a, &b的值分別賦值給c1, c2,後續的一些操作在交換的是cp1和cp2指向的地址,並沒有操作cp1和cp2指向的地址的值,因此不會影響main函數中的變量a, b的值。
-gdb調試過程:
swap3中各個變量在內存中的情況:
在調用swap3(char *cp1, char *cp2)時,- 會產生對應的兩個臨時指針變量cp1, cp2,程序會將&a, &b的值分別賦值給cp1, cp2
- 使用*cp1讀取到cp1指向的內存空間中的數據賦值給臨時變量tmp,此時tmp的值變爲變量a的值
- 使用*cp2讀取到cp2指向的內存空間中的數據(b的值),並將數據寫到cp1指向的內存空間(&a)中,
覆蓋掉原來的數據(原來存放的是變量a的值),此時cp1指向的內存空間中存儲的就是b的值了,
也就是說變量a裏存放的數據變成了變量b的值 - 將tmp的值寫到cp2指向的內存空間(&b)中,覆蓋掉原來的數據(原來存放的是變量b的值),此時cp2
指向的內存空間中存儲的就是tmp的值了,也就是說變量b裏存放的數據變成了最開始的變量a的值
-gdb調試過程:
swap4中各個變量在內存中的情況比較簡單,就不畫圖了,直接上gdb調試的圖:
-gdb調試過程: