20160206.CCPP體系詳解(0016天)
程式碼片段(01):.指標.c+02.間接賦值.c
內容概要:記憶體
///01.指標
#include <stdio.h>
#include <stdlib.h>
//01.取地址操作符(&)詳解:
// 1.操作物件:變數名(實質:記憶體實體|資料實體)
// 2.操作特點:屬於暫存器操作(操作結果不是記憶體實體)
// (1).取地址操作(&變數名)是在CPU的暫存器區域所完成的操作;
// (2).地址資料不佔用記憶體,記憶體地址是在CPU核心構成元件暫存器產生的,
// 記憶體地址的數值和記憶體儲存沒有實質關係;
// 3.計算機地址匯流排:連線CPU與硬體記憶體的匯流排
// (1).匯流排數目與CPU位數+作業系統位數有關
// (2).地址數值作為一個常量恆久不變
// (3).地址作為產量恆值並不會佔用記憶體
// 記憶體地址是在CPU的暫存器當中產生的,因此不具備記憶體實體,也就不會佔用記憶體
// (4).匯流排的個數決定者位數的不同:
// 32條匯流排對應於32位作業系統;64條匯流排對應於64位作業系統
//02.對指標變數的解釋:
// P一個指標變數,用於儲存普通變數的地址數值,然後通過操作指標變數的方式間接操作普通變數
//03.對於指標所佔用的位元組數分析:
// Win32平臺所編譯的程式的指標型別佔用4個位元組
// Win64平臺所編譯的程式的指標型別佔用8個位元組
int main01(void)
{
int num = 10;
int data = 20;
//P是一個指標變數,可以儲存相同型別的不同變數的記憶體地址,常用於做間接訪問變數本身(記憶體實體)操作
int * pNum = #//0x12312312
int * pData = &data;
printf("%d \n", sizeof(pNum));//指標變數所佔用的記憶體尺寸為4個位元組(Win3平臺所編譯的程式)
printf("%p \n", pNum);//直接列印指標變數(pNum)的數值,相當於間接列印了普通變數(num)的地址
printf("%p \n", &pNum);//表示獲取"指標"變數的地址,型別為int **
system("pause");
}
//04.指標變數內容詳解:
// 1.型別:
// 既決定了記憶體實體步長,也決定了記憶體實體解析方式
// 2.數值:
// 就是一個地址數值
// 3.場景:(攜帶*號的情況)
// 賦值號左邊:
// 給記憶體實體寫入資料
// 賦值號右邊:
// 從記憶體實體讀取資料
int main02(void)
{
int num1 = 1100;
int num2 = 1200;//變數num都分配了記憶體,記憶體實體(資料實體)的數值代表變數的資料
int * pNum = &num1;//pNum1是int型別的一級指標變數,&num1是一級指標真常量數值(含有型別含義)
pNum = &num2;//pNum的值是num2這個變數(記憶體實體|資料實體)的記憶體地址,該記憶體地址統一佔用4個位元組,int * 地址,指標變數的長度統一為4
//int * 對稱於pNum,指標型別既決定了記憶體實體的訪問位元組步長,也決定了記憶體實體的解析方式,特殊點:浮點型資料的特殊儲存形式,既是指數形式儲存還涉及到無符號型別(儲存實質階碼)
*pNum = 12;//通過指標變數間接的訪問了普通變數的記憶體實體//根據指標數值找到記憶體地址,根據指標型別既決定了儲存步長也決定了儲存方式
printf("%p \n", &pNum);//&pNum表示獲取一級指標變數pNum的記憶體地址,該地址數值儲存於CPU核心元件暫存器區域,完全不會佔用記憶體儲存
printf("%d \n", num2);
printf("num2 = %d \n", num2);
system("pause");
}
//05.野指標:就是沒有進行初始化操作的指標變數
// VC:編譯檢測,GCC編譯不檢測
//06.解析方式的不同含義:
// 有無符號:signed/unsigned
// 儲存原理:補碼原理/階碼原理
//07.指標變數所佔用的記憶體尺寸只跟編譯平臺有關:
// Win32平臺:4位元組-->Win64平臺:8位元組
int main03(void)
{
//int * p;//沒有物件的野指標,定義指標變數的時候必須進行指標變數的初始化操作
//printf("%p \n", p);//列印指標變數當中所儲存的記憶體地址-->編譯不通過
//解析方式的不同特點:
// signed/unsigned(只針對於10進位制的整數)+float指數形式儲存(階碼實質儲存)
int num1 = 10;
int num2 = 20;
//float * pNum;
//pNum = &num1;
//printf("%f", *pNum);//指標變數的型別決定了指標變數對其所儲存的地址數值的解析步長(位元組尺寸)以及解析方式(補碼階碼)
int * pNum;
pNum = &num1;
printf("%d \n", *pNum);//對記憶體地址數值的正確解析步長和正確解析方式
printf("%d \n", sizeof(pNum));//指標變數所佔用的位元組長度在Win32平臺之下統一佔用4個位元組的記憶體尺寸,任何型別的地址都一樣採用int型別的統一位元組尺寸儲存
printf("%d \n", sizeof(*pNum));//尺寸,方式
system("pause");
}
//08.指標認識規律:
// *pNum<=>num
int main04(void)
{
int num = 20;
int data = 30;
int * pNum = #//int型別的一級指標變數儲存了int型別的普通變數的記憶體地址
//&num = 1;//記憶體地址不允許操作,由於&num這個表示式是在CPU的暫存器當中所進行的操作,然而C語言是不能夠直接修改暫存器當中的資料的
//pNum = &data;
num = 3;
printf("%d,%d \n", *pNum, num);//*pNum和num是完全等價的
*pNum = 7;
printf("%d,%d \n", *pNum, num);
system("pause");
}
///02.間接賦值.c
#include <stdio.h>
#include <stdlib.h>
//01.函式形參具有副本機制:
// 1.傳值和傳指的資料層面意思都一樣;
// 只不過對同樣的數值有著不同的解析方式!
// 1.函式的副本機制總是存在;
// 無論是傳值還是傳地!
void change05(int num)//函式形參具有副本機制
{
//函式形參具有副本機制,因此,無論是傳值還是傳指,都具備這樣的特性:
// 傳值傳遞的是副本,傳指傳遞的是地址,因此出現不一樣的修改效果
// 實質:都是副本,只不過對待同樣的數值解析方式不同而已
num = 3;
printf("change05 = %d \n", num);
}
int main05(void)
{
int num = 10;
change05(num);
printf("%d \n", num);
system("pause");
}
void change06(int * pNum)
{
*pNum = 3;
}
int main07(void)
{
int num = 10;
change06(&num);//&num-->表示式-->沒有記憶體實體-->位於暫存器-->C語言不具備修改暫存器的許可權
printf("%d \n", num);
system("pause");
}
程式片段(02):01.Run.c
內容概要:掛
#include <stdio.h>
#include <stdlib.h>
//01.外掛修改數值原理
// 1.注入DLL模組兒
// 2.根據指標進行跨函式訪問記憶體
_declspec(dllexport) void go()
{
int * p = (int *)0xae0720;
*p = 77;
}
//02.遍歷記憶體查詢原理:
// 1.單位元組記憶體遍歷
// 2.待查詢尺寸讀取
_declspec(dllexport) void run()
{
typedef char * Char;
for (Char pStart = 0xae000000,pEnd = 0xae100000; pStart < pEnd; ++pStart)//單位元組遍歷指定記憶體範圍
{
int * p = (int *)p;//指標型別轉換,待查詢尺寸讀取資料進行匹配,以便於相同數值進行記憶體檢索
if (77 == *p)
{
*p = 86;
}
}
}
程式片段(03):01.void.c+02.空指標.c
內容概要:Void與空型別指標
///01.void.c
#include <stdio.h>
#include <stdlib.h>
//01.空型別與空型別指標:
// 空型別:void
// 空型別指標:void *
//02.指標型別:
// 解析步長+解析方式
//03.空型別指標變數:
// 可以儲存任何型別的指標
int main01(void)
{
//error C2182:"a":非法引用"void"型別 void
int num = 10;
double db = 19.3;
//void num;//不合法-->沒有明確資料型別-->編譯器既不知道分配多大步長的記憶體塊兒,也不知道按照何種方式進行分配!
void * vp = #//合法->Win平臺(32/64)編譯器明確指標所應使用的記憶體位元組尺寸-->不需要明確解析方式-->因為只是一個數值意義的地址
vp = &db;//空型別的指標可以儲存任何型別變數(普通變數,一級指標變數,二級指標變數,三級指標變數,多級指標變數等等...)的地址,因為編譯器決定了地址儲存尺寸
//printf("%d \n", *vp);//:error C2100:非法的間接定址(問題原因通常是採用空型別的指標對該指標所儲存的地址進行解析)->既不明確解析尺寸,也不明確解析方式,所以出錯
//空型別的指標既不可以間接取值,也不可以間接賦值(也就是隻能儲存記憶體地址,而不能根據記憶體地址進行間接訪問操作)
//*vp = 10;
printf("%f \n", *((double *)vp));//將空型別的指標轉化為具體指標型別,然後就達到了既明確了指標的解析步長,也明確瞭解析方式
system("pause");
}
///02.空指標.c
#include <stdio.h>
#include <stdlib.h>
//01.結構體變數:
// 用於組織多種不同型別的變數
struct MyStruct//包含四根指標,花心的妹子,可以進行動態的擴充
{//一個由多個一級指標變數所構成的單個普通結構體變數
int *p1;
int *p2;
int *p3;
int *p4;
};
//02.空指標(NULL):
// 實質:(void *)0
// 作用:標識任何指標變數沒有儲存記憶體地址
// 特點:空指標所指向的記憶體實體不允許訪問,否則出現訪問異常
int main02(void)
{
//標記指標變數是否儲存記憶體地址
double db = 10.9;
double 劉海華 = 10.9;
double * pDb = NULL;//空指標(NULL):標識任何指標變數沒有儲存記憶體地址
while (NULL == pDb)
{
//炮之
pDb = &劉海華;
}
*pDb = 1;//空指標所指向的記憶體實體不允許進行操作
system("pause");
}
程式片段(04):01.指標的宣告.c
內容概要:指標的宣告
#include <stdio.h>
#include <stdlib.h>
//01.宣告指標變數:
// 資料型別+指標級數+指標變數
int main01(void)
{
int * p1;
int * p2;
system("pause");
}
//02.特殊宣告格式:
// 格式:資料型別 * p, num;
// 特點:p是指標變數,num是普通變數
int main02(void)
{
int numA, numB, numC;
double * pNumA, pNumB, pNumC;
printf("%d \n", sizeof(pNumA));//在Win32平臺之下,所有型別,所以級數的指標變數都佔用4個位元組的記憶體尺寸
printf("%d \n", sizeof(pNumB));
system("pause");
}
//03.巨集定義(巨集替換)和別名定義的區別:
// 巨集定義:第二整塊兒替換後置
// 別名定義:最後整塊兒替換前置
#define 整數 int
typedef int INT;
int main03(void)
{
整數 x = 3;//替換後置
INT y = 3;//替換前置
printf("%d, %d \n", x, y);
system("pause");
}
//04.別名定義規律:
// 變數定義:int * pNum
// 添關鍵字:typedef int * pNum;
// 特點:變數名變為型別別名
#define 指標 double *
typedef double * DBP;
int main04(void)
{
指標 p1;
DBP p2;
//printf("%p, %p \n", p1, p2);
printf("%d, %d \n", sizeof(p1), sizeof(p2));
system("pause");
}
//05.特別注意:
// 1.巨集定義(巨集替換)和別名定義之間的區別
// 2.預編譯與真實別名
int main05(void)
{
指標 p1, p2;//實質:double *p1, p2, p3;//4,8
p1 = 0x123;
p2 = 0x123;
DBP p3, p4;//doube *型別
p3 = 0x123;
p4 = 0x123;
printf("%d, %d \n", sizeof(p1), sizeof(p2));
printf("%d, %d \n", sizeof(p3), sizeof(p4));
system("pause");
}
程式片段(05):01.銀行.c+02.指標陣列.c
內容概要:資料地址對映
///01.銀行.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//01.C語言編譯器特點:
// 未初始化的普通變數->編譯通過
// 未初始化的指標變數->編譯不過
//02.資料地址對映使用:
// 1.不允許改變原始記憶體實體的情況,實現排序
// 2.比較資料實體,交換指標變數
// 注:
// 1.只有整型資料才能使用位運算
// 2.升序的反面成立,既需要進行交換
int main01(void)
{
int num1;//記憶體實體
int num2;
scanf("%d%d", &num1, &num2);//從從小到大
int * p1 = &num1;//對映指標
int * p2 = &num2;
if (*p1 > *p2)//升序的反面成立,就需要進行交換
{
//p1 = p1 ^p2;//只有整型才能使用位運算
int * ptemp = p1;
p1 = p2;
p2 = ptemp;
}
printf("%d, %d \n", *p1, *p2);
system("pause");
}
//03.指標變數宣告與const關鍵字使用:
// 規律:const在指標變數名稱前面,也就是星號("*")的右邊
// 就表明該指標變數本身是一個偽常量,也就是該指標變數
// 不能直接進行修改,但是可以通過間接方式進行修改
// 特點:const int * p<=>int const * p
// 只需要關注const與星號("*")之間的相對位置
// 用處:限定訪問許可權
// 讀取許可權和修改許可權的綜合配對
//void accessControl(const int * p);
void accessControl(int const * p)//報表許可權:限定訪問許可權,間接操作的記憶體實體只能讀取,不能進行修改
{//const在指標當中所能起到的作用
p = NULL;//通過指標變數間接訪問的記憶體實體是個真常量,不允許進行間接修改,但是當前指標變數可以進行修改
printf("*p = %d \n", *p);//不能根據空指標進行記憶體實體訪問,既不能讀取也不能寫入(作業系統規定)-->編譯不報錯,但是執行報錯
//*p = 10;//編譯報錯
}
int main02(void)
{
int num = 100;
int * pNum = #
accessControl(pNum);
printf("num = %d \n", num);
system("pause");
}
///02.指標陣列.c
#include <stdio.h>
#include <stdlib.h>
//int a[8];
//const int *p[8];
int a[8] = { 1,8,2,7,3,6,4,5 };//int型別的陣列
const int * p[8] = { &a[0],&a[1],&a[2],a + 3,a + 4,a + 5,a + 6,a + 7 };//指標陣列
void main()
{
printf("原來的陣列資料:\n");
for (int i = 0; i < 8; i++)
{
printf("%d\n", a[i]);
}
printf("原來的指標陣列指向資料:\n");
for (int i = 0; i < 8; i++)
{
printf("%d\n", *p[i]);
}
for (int i = 0; i < 8 - 1; i++)//最後一個資料不需要冒泡
{
for (int j = 0; j < 8 - 1 - i; j++)//冒泡數與與i形成對應關係
{
//指標陣列當中儲存的是指標,然後通過指標進行資料的獲取,通過比較指標所對應的資料,然後進行資料交換
if (*p[j]>*p[j+1])//這裡使用指標陣列進行比較資料,用陣列指標進行資料獲取比較,然後進行資料交換
{//指標交換
int *ptemp = p[j];
p[j] = p[j + 1];
p[j + 1] = ptemp;
}
}
}
printf("陣列資料:\n");
for (int i = 0; i < 8; i++)
{
printf("%d\n", a[i]);
}
printf("指標陣列指向資料:\n");
for (int i = 0; i < 8; i++)
{
printf("%d\n", *p[i]);
}
system("pause");
}
程式片段(06):01.輸入指標.c
內容概要:地址輸入
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main01(void)
{
int num = 10;
int data = 20;
printf("%p, %p \n", &num, &data);
int * pNum = &pNum;
//對指標變數進行手動地址輸入:
// 格式:scanf("%p", &pNum);
// 特點:不需要攜帶0x字首,而且必須是大寫英文字母
scanf("%p", pNum);//地址型別陣列需要使用%p這種輸入格式控制符+指標變數的地址
*pNum = 20 + 3;//作業系統所使用的地址,胡亂進行訪問的時候容易出現系統問題
printf("num = %d, data = %d \n", num, data);
system("pause");
}
程式片段(07):01.Screen.c
內容概要:螢幕輸出圖片
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int main(void)
{
int i = 0;
while (1)
{
HWND win = GetDesktopWindow();
HDC winDc = GetWindowDC(win);//獲取指定視窗的輸出介面
HDC memDc = CreateCompatibleDC(0);//獲取記憶體儲存的操作介面
HBITMAP bitMap = (HBITMAP)LoadImage(win, TEXT("1.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
SelectObject(memDc, bitMap);//選定圖形影象裝置-->設定顯示什麼
BitBlt(winDc, 0, 0, i++, i++, memDc, i++, i++, SRCCOPY);
Sleep(100);//模擬0.1秒
++i;
if (3 == i)//到達3次
{
i = 0;//重置0次
}
}
system("pause");
}
程式片段(08):test.c
內容概要:Test1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define EN 1024
int flag = 0;
char * filePath = "E:\\Resource\\TestData\\BigDB\\Test.txt";
//陣列賦值
int intArr[EN];
void initArr(int intArr[EN])
{
//time_t te;
//unsigned int seed = (unsigned int)(time(&te));
//srand(seed);
srand((unsigned int)(time(NULL)));
for (int i = 0; i < EN; ++i)
{
intArr[i] = rand() % EN + 1;
}
}
//陣列顯示
void showArr(int intArr[EN])
{
for (int i = 0; i < EN; ++i)
{
printf("%4d \n", intArr[i]);
}
}
//氣泡排序
void bubbleSortArr(int intArr[EN])
{
for (int i = 0; i < EN - 1; ++i)
{
for (int j = 0; j < EN - 1 - i; ++j)
{
if (intArr[j] > intArr[j + 1])
{
intArr[j] = intArr[j] ^ intArr[j + 1];
intArr[j + 1] = intArr[j] ^ intArr[j + 1];
intArr[j] = intArr[j] ^ intArr[j + 1];
}
}
}
}
//選擇排序
void selectSortArr(int intArr[EN])
{
int minIndex = 0;
int minNum = 0;
for (int i = 0; i < EN - 1; ++i)
{
minIndex = i;
minNum = intArr[i];
for (int j = i + 1; j < EN; ++j)
{
if (minNum > intArr[j])
{
minIndex = j;
minNum = intArr[j];
}
}
if (i != minIndex)
{
intArr[i] = intArr[i] ^ intArr[minIndex];
intArr[minIndex] = intArr[i] ^ intArr[minIndex];
intArr[i] = intArr[i] ^ intArr[minIndex];
}
}
}
//插入排序
void insertSortArr(int intArr[EN])
{
int currentIndex = 0;
int currentValue = 0;
for (int i = 1; i < EN; ++i)
{
currentIndex = i;
currentValue = intArr[currentIndex];
while (0 < currentIndex && intArr[currentIndex - 1] > currentValue)
{
intArr[currentIndex] = intArr[currentIndex - 1];
--currentIndex;
}
intArr[currentIndex] = currentValue;
}
}
//二分查詢
int binarySearch(int intArr[EN], int value)
{
int minIndex = 0;
int midIndex = 0;
int maxIndex = EN - 1;
while (minIndex <= maxIndex)
{
midIndex = (minIndex + maxIndex) / 2;
if (value == intArr[midIndex])
{
return midIndex;
}
else if (value < intArr[midIndex])
{
maxIndex = midIndex - 1;
}
else
{
minIndex = midIndex + 1;
}
}
return -1;
}
//拉格朗日查詢
int lagrangeSearch(int intArr[EN], int value)
{
int minIndex = 0;
int ratioIndex = 0;
int maxIndex = EN - 1;
while (minIndex <= maxIndex)
{
//midIndex = minIndex + (maxIndex - minIndex) / 2;
ratioIndex = minIndex + (maxIndex - minIndex)*(value - intArr[minIndex]) / (intArr[maxIndex] - intArr[minIndex]);
if (value == intArr[ratioIndex])
{
return ratioIndex;
}
else if (value < intArr[ratioIndex])
{
maxIndex = ratioIndex - 1;
}
else
{
minIndex = ratioIndex + 1;
}
}
return -1;
}
int main01(void)
{
initArr(intArr);
showArr(intArr);
insertSortArr(intArr);
printf("binSearch Index = %d \n", binarySearch(intArr, 880));
printf("lagrangeSearch index = %d \n", lagrangeSearch(intArr, 880));
system("pause");
}
相關文章
- 20160217.CCPP體系詳解(0027天)
- 20160124.CCPP詳解體系(0003天)
- 20160125.CCPP詳解體系(0004天)
- 20160126.CCPP體系詳解(0005天)
- 20160127.CCPP體系詳解(0006天)
- 20160130.CCPP體系詳解(0009天)
- 20160203.CCPP體系詳解(0013天)
- 20160211.CCPP體系詳解(0021天)
- 20160213.CCPP體系詳解(0023天)
- 20160214.CCPP體系詳解(0024天)
- 20160215.CCPP體系詳解(0025天)
- 20160224.CCPP體系詳解(0034天)
- 20160218.CCPP體系詳解(0028天)
- 20160219.CCPP體系詳解(0029天)
- 手遊《天地劫》的三天體驗——深度系統剖析及玩法詳解
- 20160122.CCPP詳解體系(0001天)
- 20160123.CCPP詳解體系(0002天)
- 20160128.CCPP體系詳解(0007天)
- 20160129.CCPP體系詳解(0008天)
- 20160131.CCPP體系詳解(0010天)
- 20160204.CCPP體系詳解(0014天)
- 20160205.CCPP體系詳解(0015天)
- 20160210.CCPP體系詳解(0020天)
- 20160212.CCPP體系詳解(0022天)
- 20160207.CCPP體系詳解(0017天)
- 20160225.CCPP體系詳解(0035天)
- 20160226.CCPP體系詳解(0036天)
- 20160227.CCPP體系詳解(0037天)
- 20160222.CCPP體系詳解(0032天)
- 20160221.CCPP體系詳解(0031天)
- 20160201.CCPP體系詳解(0011天)
- 20160202.CCPP體系詳解(0012天)
- 20160209.CCPP體系詳解(0019天)
- 20160216.CCPP體系詳解(0026天)
- 20160208.CCPP體系詳解(0018天)
- 20160223.CCPP體系詳解(0033天)
- 20160220.CCPP體系詳解(0030天)
- MySQL體系結構詳解MySql