return 函式在主函式中return結束程式。在其他函式中return結束該函式,但程式仍執行。
exit 在任何函式中執行都會結束程式,也就是結束程序。
如果函式不是寫在main函式前邊,那麼需要在函式被呼叫的前邊某個地方宣告。
乙個函式可以宣告多次,但只能定義一次,宣告的變數名稱和定義的變數名稱可以不一樣。甚至宣告時候可以只寫形參型別,不寫形參名字。
分檔案程式設計: 按功能來分,不同的功能寫在不同的檔案中。***.h、***.c
一次性編譯多個.c檔案辦法, 某個函式在乙個檔案定義,另外乙個檔案中宣告這個函式後,就可以呼叫了。
gcc main.c mystrlen.c -o test或者gcc *.c -o test
多個檔案中不能出現同名函式,static除外。
函式定義內容不寫到.h中原因是:可能乙個.h會被多個.c檔案呼叫,會造成乙個函式在多個.c中被定義了,所以出錯。
函式的宣告一般寫到.h中,.h檔案中可以宣告多個函式,呼叫的主函式可以只寫一句#include"***.h"即可,不用多寫幾句函式宣告。
另外函式宣告寫到.h檔案中,雖然
可能乙個.h會被多個.c檔案呼叫,會造成乙個函式在多個.c中被定義宣告了,但是函式本身就可以多次宣告,但只能一次定義。
同乙個檔案如何避免對同乙個.h檔案同時包含:
1、在標頭檔案地方加上 #pragma once
2、#ifndef ***_h
#define ***_h
標頭檔案正文
#endif
a.out存在於硬碟(rom)中, 我們執行a.out時候把程式載入到記憶體(ram),執行著的程式叫程序。這裡的記憶體也就是記憶體條。記憶體是溝通cpu和硬碟的橋梁
棧位址分配時候從高到低遞減找到合適的大小分配。
1、記憶體是以1位元組為單位的
2、每個位元組的記憶體都有標號,這個標號就是位址,也就是指標。
3、位址需要儲存, 32位編譯器使用32位(4位元組)儲存此位址
64位編譯器使用64位(8位元組)儲存此位址
4、每個儲存單元(1位元組)分配乙個號碼,就叫編碼。
5、根據位址找到對應記憶體,也叫定址。
char ch;
int a=10;
ch/*ch佔1位元組*/
/*高位址*/
a/*a佔4位元組*/
a/*a佔4位元組*/
a/*a佔4位元組*/
a/*a的首位址=&a*/
/*低位址*/
指標就是位址,位址就是指標。
指標變數時存放位址的變數,習慣上叫做指標。
1、指標也是一種資料型別。
int * 也是一種型別, int * p; p也是乙個變數,p的型別為int *, 可以對p進行賦值。
p=(int *)123;或者 p = 123;
printf("%p",p);
gcc hello.c -w 忽略列印
2、指標指向誰,就把誰的位址賦給指標。
int a=10;
int * p;
p = &a;
printf("%p",p);和printf("%p",&a);結果一樣
3、直接操作指標變數p沒意義,
4、操作*p代表操作指標所指向的記憶體, *p代表a。
*p=100;
printf("%d",*p);和printf("%d",a);結果一樣
*符號有兩層含義:
1、在定義變數時,*代表型別,它是指標型別 如 int *p;
2、在使用變數時, *代表操作指標指向的記憶體。如 *p=100;
編譯時候段錯誤一般都是記憶體出錯。
操作野指標變數本身沒有問題,但是操作野指標所指向的記憶體才導致段錯誤。
關於空指標兩個好的習慣:
1、定義指標時候立馬給這個指標賦值為空指標null;
2、給指標指向位址賦值之前最好檢查一下,確認指標不是空指標。
指標大小:
32位編譯器用32位(4位元組)大小儲存位址大小
64位編譯器用64(8位元組)位大小儲存位址大小
vs若想測試64位編譯器可以在debug下拉三角下配置一下編譯管理器,活動平台選擇x64。
多級指標:
如果定義乙個合適型別的變數儲存另乙個變數的位址。在需要儲存變數位址型別的基礎上加乙個*號。
int a=10;
int *p=&a;
int * *q = &p;// 儲存p的位址,所以在p的型別int *基礎上再加乙個*號變為int **;
int ** *t = &q;// 儲存q的位址,所以在q的型別int **基礎上再加乙個*號變為int ** *;
int *** *m = &t;// 儲存t的位址,所以在t的型別int ***基礎上再加乙個*號變為int *** *;
*m代表t的值,所以*m==t==&q
**m代表*t,*t代表q,即 **m代表q, 所以**m==*t==q=&p;
***m代表**t,**t代表*q, *q代表p, 即***m代表p,所以***m==**t==*q=p=&a;
****m代表***t,***t代表**q, **q代表*p, *p代表a ,即 ****m代表a, 所以****m==***t==**q=*p=a;
總結:多級指標不是看多少星,而是看什麼型別的變數。
1、指標變數也是乙個變數, 是變數就可以進行賦值。
2、指標指向誰,就把誰的位址賦給指標
3、*p操作的是指標指向的記憶體。
不僅僅代表陣列
,*p等價於*(p+0)同時等價於p[0]. 實質上記憶體是乙個大陣列,能用指標的地方就能用陣列。
*(p+i)等價於p[i]
int a=10;
int *p = &a;
printf(「%d %d %d」,a, *p, p[0]);
萬能指標: void *
1、不能編譯定義 void型別的變數,因為無法確定型別,編譯器不知道型別就不知道分配多少位元組記憶體。
2、可以定義void *型別變數,因為指標大小是確定的,編譯器是多少位的,指標大小占用記憶體就是多少位的。
3、void *可以指向任何型別的變數。使用指標所指向的記憶體時,最好轉換為它本身的指標型別。
void *p=null;
int a=10;
p=&a; //err因為這樣話編譯器雖然知道首位址但不知道*p到底操作多大記憶體,若是int *則從首位址開始操作4位元組, 若是char *則從首位址開始操作1位元組。
* ((int *)p) =222; //先將p指標變數強制轉化為(int *),然後再對p指向的記憶體進行操作,這次知道是操作4位元組。
printf("*p =%d \n", *( (int*)p) );
指標步長; int *p; p+1和p值相差為4(int *指標步長為4), 因為*p操作的是int型變數,每次操作需要4個位元組。同理 char *q的指標步長為1.
const 修飾的指標變數。
int a=10;
const int *p =&a; //const修飾的是*(const從左往右數 跳過int 修飾的是*),代表指標所指向的記憶體是唯讀。
*p=200;// err編譯不通過。
p=null;//ok,這條語句可以編譯通過
int const * p2 =&a; //const修飾的還是是*,代表指標所指向的記憶體是唯讀。
*p2=300;// err 同樣編譯不通過,
p2=null;//ok,這條語句可以編譯通過
int * const p3 =&a; //const修飾的是指標變數p3,代表指標變數的值是唯讀。
*p3=400;// ok, 這條語句可以編譯通過
p3=null;//err編譯不通過。 p3是常量指標,指向的位址不能改,指向哪就是指向哪。
類似於陣列名,陣列名的位址也不能改。
const int * const p4 =&a; //這個什麼都改不了, 變數不能改, 指標指向的位址不能改。
陣列名是常量,陣列名類似於常指標,其指向首位址,指向的位址不能改。
int a[5]=;
int *p = null;
p =a; 或者p= &a[0];
for(int i=0; i<5; i++)
1、不使用排序找出第二大的數
2、不用庫函式實現字串拷貝功能。
C 學習筆記day08
1 排序函式 void order int p1,int p2 sort ia 9,sizeof int orderint for int i 0 i 9 i coutpers 0 id 1 pers 0 age 29 strcpy pers 0 name liucy pers 1 id 2 per...
java基礎學習day08總結
1.物件導向,面向過程 1 物件導向,面向過程都是一種思想,物件導向是相對面向過程來來說的 面向過程強調的是執行的過程,而物件導向是將功能進行封裝,對功能進行呼叫,強調的是呼叫,比如人開啟門的過程,門開啟則是面向過程,而人開啟門則是物件導向的過程。2 物件導向的三大特點 封裝 繼承 多型 2.類和物...
學習筆記day08
單例設計模式 上圖中,想要實現a,b的配置資訊共享,因為a,b是兩個new,所以必然是不同的物件,一種方法就是將其配置資訊全部設成靜態,但資訊很多時會導致儲存資訊過多。單例設計模式流程 1,主函式main進棧,定義s1 2,等號右邊,single載入進入方法區,接著是single的建構函式。s和ge...