程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> [ndk,1]ndk開發,C語言入門講解

[ndk,1]ndk開發,C語言入門講解

編輯:關於C

一、C語言helloworld案例入門:

 

#include //引入頭文件(引入函數庫)相當於java import的操作

#include

main() //主函數,跟java類似 程序的入口函數

{

printf("Hello world !\n"); //在控制台輸出

system("java cn.itcast.demo.HelloWorld");//調用執行java文件

system("pause");

}

 

//system("pause");是:調用cmd裡面的暫停命令,讓cmd窗口暫停執行以下 ,方便我們觀察程序的執行結果.

 

二、C語言的基本數據類型:

c語言的數據類型

char, int, float, double, signed,unsigned, long, short and void

 

1.在c99的語法的中 是沒有boolean的數據類型的,true false 非0代表真 0代表的是假.

2.c語言裡面沒有byte類型 ,

如何讓c語言表示 java中的byte呢? 可以利用char類型代替java中的byte類型

 

3.c語言裡面沒有String的字符串 , c想表示一個字符串 一般是通過char數組來表示的

sizeof(); 參數是數據類型 返回值就是這個數據類型在內存中占用多少空間

4. 注意: signed, unsigned:只能修飾整數類型的數據 不能修飾浮點型的數據。

signed表示有符號,unsigned表示無符號。

 

5.java中的char是兩個字節 ,c語言裡面 1個字節

*/

#include //引入頭文件 java import的操作

main()

{ // %d 代表的是一個占位符

printf("char占用的字節為%d\n",sizeof(char)); 1個字節

printf("int占用的字節為%d\n",sizeof(int)); 4個字節

printf("float占用的字節為%d\n",sizeof(float)); 4個字節

printf("double占用的字節為%d\n",sizeof(double)); 8個字節

printf("short占用的字節為%d\n",sizeof(short)); 2個字節

 

printf("long占用的字節為%d\n",sizeof(long));

printf("signed int占用的字節為%d\n",sizeof(signedint));

printf("unsigned int占用的字節為%d\n",sizeof(unsignedint));

 

//printf("unsigneddouble占用的字節為%d\n",sizeof(unsigned double)); 該行代碼會報錯。

system("pause");

 

}

三、輸入輸出函數:

1、C語言中的刪除操作使用占位符實現的,不同類型的數據對應不同占位符:

%d - int

%ld – long int

%c - char

%f - float

%lf – double

%x – 十六進制輸出 int 或者long int 或者short int

%o - 八進制輸出

%s – 字符串

%hd - short

short

 

2、C語言的輸入函數:

Int len;

Scanf(“%d”,&len); //掃描鍵盤的輸入函數:

參數1:輸入數據的指定類型的占位符。

餐宿2:指定保存輸入數值的變量地址。

 

例:

#include //引入頭文件 java import的操作

main()

{

int i = 129024;

long l = 333L;

char c ='B';

float f = 3.1415926f;

double d = 3.1415;

short s = 257;

 

printf("int i =%d\n",i);

printf("int l =%ld\n",l);

printf("int c =%d\n",c);

printf("int f =%f\n",f);

printf("int d =%lf\n",d);

printf("short s=%hd\n",s);

 

char cc;

printf("請輸入一個int類型的值\n");

//& 取地址

scanf("%c",&cc);

printf("char cc =%c\n",cc);

//接收輸入的字符串:使用char數組:

//定義一個char類型的數組 叫arr 用來存放字符串

char arr[]={' ', ' ',' ','',' '};

printf("請輸入一個字符串\n");

scanf("%s",arr);

printf("數組的內容%s\n",arr);

system("pause");

 

}

 

四、指針:

1、所謂指針就是一個地址,地址其實就是一個內存空間的編號.

2、每個變量在內存中都有一個地址 :通過& 符號獲取變量的地址.

例:

#include

main(){

int i;

//把i變量在內存中的地址 打印出來

 

//打印出變量的地址,指針就是一個地址 ,

//地址為十六進制:如:0xXXXX ,#表示打印的數值前面帶0x

printf("i的地址為%#x\n",&i);

 

//60秒的倒計時

for(i =60; i>0;){

 

printf("剩余時間%d\n",i);

sleep(4000);

 

i--;

}

 

printf("游戲結束\n");

system("pause");

}

3、指針和指針變量:

例:

#include

main(){

// 1. 指針就是地址, 通過一個地址可以訪問到一塊內存空間, 如果修改這個內存空間裡面的內容

 

int i = 5; //定義一個int類型的變量 變量的名字 叫 i 裡面存放的內容 是一個int類型的值

// 2. 指針變量 用來存放一個變量地址的變量

int* p; //定義了一個int* 類型的變量 變量的名字叫p 裡面存放的內容 是一個

//int* 類型的值

//也可以定義為:int *p; 或 int * p;

 

p = &i; // p裡面存放的就是 i變量的地址了.

 

printf("p的值為%#x\n",p);

// 指針和指針變量的關系

// 指針是一個地址 ..

// 指針變量是存放一個地址的變量

//其實是兩個完全不同的概念,但是 世面的書籍 習慣上把指針跟指針變量沒有做區別

 

// * 號操作符的使用:

 

1.使用場景,定義一個指針變量 int* double* long*

2.表示兩個數據相乘 3*5 = 15;

3. 如果*號後面跟的是一個指針變量, 用*可以訪問指針變量內部存放的地址 裡面存儲的變量

 

 

//*p; //獲取p變量裡面存放地址所指向的變量,就是i對應的值;

//*p 和 i 代表的是同一個變量

printf("*p的值為%d\n",*p);

system("pause");

}

 

五、指針的常見錯誤:

1、指針未經賦值不能使用: 以下代碼會報錯:

#include

main(){

int i = 5;

int* p ;

printf("*p的值為%d\n",*p);

system("pause");

}

2、不同的指針類型 不能進行相互的轉化

#include

/**

不同的指針類型 不能進行相互的轉化

每一種變量類型 在內存中占用的空間 是不相同的.

*/

 

main(){

short s = 278;

 

int i = 2777777; //4個byte

 

int* p = &i;

short* q = &i; // short 在內存空間裡面占用的是兩個 byte

 

printf("*p=%d\n",*p);

printf("*q=%hd\n",*q);

 

 

 

system("pause");

}

3、不能使用已經被系統回收掉的內存空間裡的數據:

 

 

 

六、案例:交換兩個數字.

通過修改地址裡面的值 達到了交換數據的目的

 

#include

void swap2(int* p, int* q){//p代表的是 i的地址, q代表的是 j的地址

 

// 把i變量和 j變量的地址 傳遞給了子函數,在子函數裡面直接通過修改地址裡面的值 達到了交換數據的目的

// *p 代表的就是 i變量

 

// *q 代表的就是 j變量

 

int temp;

temp = *p;

*p = *q;

*q = temp;

 

 

}

//主方法

main(){

int i = 3;

int j = 5;

// swap(i,j);

 

swap2(&i,&j);

printf("i=%d\n",i);

printf("j=%d\n",j);

 

system("pause");

}

 

七、指針的作用:

1、直接訪問硬件 (opengl 顯卡繪圖)

2、 快速傳遞數據(指針表示地址)

3、 返回一個以上的值(返回一個數組或者結構體的指針)

 

例:在子函數中同時修改兩個變量對應的值:

#include

 

//相當於是讓子函數 修改了主函數裡面連個數據的值, 子函數返回一個以上的數據

void f(int* p , int* q){ // p表示的是i的地址, q代表的是 j的地址

*p = *p+3;

*q = *q+3;

 

}

main(){

 

int i = 3;

int j = 5;

f(&i,&j); //調用子函數

printf("i=%d\n",i);

printf("j=%d\n",j);

 

system("pause");

}

4、 表示復雜的數據結構(結構體)

5、 方便處理字符串

// c語言是沒有String類型的 要在c語言裡面表示一個字符串 一般都是通過字符數組的方式表示

 

#include

main(){

// char arr[]={'h','e','l','l','o'};

 

//char類型的指針變量

char* arr ="hello";

//輸出字符傳

printf("%s\n",&arr[0]);//arr[0]字符數組的首地址。

 

system("pause");

}

 

6 、指針有助於理解面向對象

 

八、指針和數組之間的關系:

1、數組:

數組在內存中是一塊連續的內存空間。

數組的名稱 等於數組中第一個元素的地址(首地址)。

int arr[]={1,2,3,4};

 

printf("arr = %#x \n",arr);

printf("第一個元素的地址為%#x\n",&arr[0]);

上面兩行代碼輸出的值相同。

2、指針操作數組:

 

例:開發一個子方法 把數組的每一個元素都打印出來

#include

 

// 第一個參數 數組的首地址, 第二個參數 數組的長度

void printArr(int* parr , intlen){

int i;

for( i=0;i

//輸出方式一:根據數組的下標獲取數組中的值:

printf("arr[%d]=%d\n",i,parr[i]);

 

// *parr //數組第一個元素對應的內容

//*(parr+1) 獲取數組第二元素對應的內容(因為內存是連續的空間)

printf("arr[%d]=%d\n",i,*(parr+i));

}

}

 

main(){

int arr[]={1,2,3,4,5,6,7,8,9};

printArr(arr,9);

system("pause");

}

九、指針的運算:

1、指針的運算只對連續的內存空間才有意義,數組是一塊連續的內存空間:

例:數組元素指針之間的運算:

#include

main(){

 

//數組是一塊連續的內存空間

int intarr[] = {1,2,3,4,5,6,7,8,9};

// int* arr0 = &intarr[0];

 

int* arr0 = intarr;//數組第一個元素的地址

 

int* arr1 = &intarr[1];

 

int* arr2 = &intarr[2];

 

printf("arr0地址為%#x\n",arr0);

printf("arr1地址為%#x\n",arr1);

printf("arr2地址為%#x\n",arr2);

 

 

printf("arr2與arr0之間的距離為%d\n", arr2 - arr0);

// 指針的運算 相減和相加得到的結果其實都是 內存地址的偏移量,不是單純的內存地址整數加減結果.結果代表的有特殊的業務含義, 幾個內存空間之間的偏移量.

 

char chararr[] ={'1','2','3','4','5'};

// int* arr0 = &intarr[0];

 

char* chararr0 = chararr;//數組第一個元素的地址

 

char* chararr1 = &chararr[1];

 

char* chararr2 = &chararr[2];

 

printf("chararr0地址為%#x\n",chararr0);

printf("chararr1地址為%#x\n",chararr1);

printf("chararr2地址為%#x\n",chararr2);

 

 

printf("chararr2與chararr0之間的距離為%d\n", chararr2 - chararr0);

 

system("pause");

}

九、指針的長度:

#include

main(){

//在32位的操作系統上, 2的32次方個內存地址 4個byte

// 在我當前的32電腦操作系統上 用的devcpp工具, gcc

 

 

int i =3;

int* ip = &i;

 

double d = 3.14159;

double* dp = &d;

 

 

float f = 6.28f;

float* fp = &f;

 

 

short s = 255;

short* sp = &s;

 

//指針的長度都為4。

printf("int的指針長度為%d\n", sizeof(ip));

 

 

printf("double的指針長度為%d\n",sizeof(dp));

 

 

printf("float的指針長度為%d\n",sizeof(fp));

 

 

printf("short的指針長度為%d\n",sizeof(sp));

 

 

 

system("pause");

}

 

十、動態內存和靜態內存:

1、動態內存

動態內存創建在堆空間上的 一塊不連續的內存空間 可以占用整個操作系統的全部內存

堆內存就是操作系統維護的剩余的內存空間,

在java裡面new出來的的所有的對象都是分配在堆內存裡面。

在C語言裡面,申請堆內存空間使用malloc 函數。

malloc函數接受一個參數 ,參數代表動態的在堆內存申請多大的內存空間.

malloc的返回值 代表的是申請的這塊內存空間的首地址.

使用free(intp);函數釋放堆內存空間,將堆內存標記為可用。

 

 

例:申請堆內存空間:

 

#include

//引入動態內存分配的頭文件

#include

 

f(int** padress){

 

//*padress 拿到了主函數裡面的p變量

 

// 申請一塊內存空間 空間的大小為8個字節,空間的首地址把他賦給 intp的變量

int* intp = (int*)malloc(sizeof(int)*2);

 

 

*intp = 33; // 在堆內存申請的空間裡面放置一個int類型的值 值為33

*(intp+1) = 99; //

 

*padress = intp; //把堆內存的地址賦給 主函數裡面的p變量

//free(intp); //釋放堆內存空間,將堆內存標記為可用。

printf("子函數i的地址為%#X\n",intp);

 

}

main(){

 

int* p ;// 用來存放 子函數裡面的i變量的地址

 

//int -> int* ->int**

 

//在主函數裡面把子函數的i變量的地址給獲取出來

f(&p);

// 手動的回收掉申請的那塊內存空間

free(p); // 99 內存中的殘留的影像,或者幻影

 

printf("主函數i的地址%#X\n",p);

printf("主函數 i的值為%d\n",*p);

printf("主函數 第二個的值為%d\n",*(p+1));

system("pause");

}

 

2、靜態內存 創建在棧空間上的 一塊連續的內存空間 2M

3、動態內存優點:

動態內存可以跨函數使用,靜態函數不可以。

動態內存中數組的長度能在函數運行中動態增加或者縮小

動態的增加數組長度:使用reallco函數。

 

例:動態的增加數組長度:使用reallco函數:

#include

//引入動態內存分配的頭文件

#include

 

void printArr(int* arr , intlen){

int i;

for(i = 0; i

printf("學生編號%d的成績為%d\n",i,arr[i]);

}

}

main(){

 

printf("請輸入學生的總數\n");

int len;

scanf("%d",&len);

 

//根據len動態的創建一個數組

 

int* pgrade = malloc(sizeof(int)*len);

 

int i;

for(i=0;i

printf("請輸入學生%d的成績\n",i);

scanf("%d",(pgrade+i));

}

 

printf("打印學生的成績列表\n");

 

printArr(pgrade,len);

 

 

printf("請輸入增加學生的個數\n");

int addnumber;

scanf("%d",&addnumber);

 

pgrade = realloc(pgrade,sizeof(int)*(len+addnumber));

int j;

for(j=len;j<(len+addnumber);j++){

printf("請輸入新添加的學生%d的成績\n",j);

scanf("%d",(pgrade+j));

}

printf("重新打印學生的成績列表\n");

 

printArr(pgrade,len+addnumber);

system("pause");

}

 

十一、堆和棧的區別:

1.申請方式

棧:

由系統自動分配.例如,聲明一個局部變量int b; 系統自動在棧中為b開辟空間.例如當在調用涵數時,需要保存的變量,最明顯的是在遞歸調用時,要系統自動分配一個棧的空間,後進先出的,而後又由系統釋放這個空間.

堆:

需要程序員自己申請,並指明大小,在c中用malloc函數

如char* p1 = (char *)malloc(10);

但是注意p1本身是在棧中的.

2 申請後系統的響應

棧:只要棧的剩余空間大於所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。

堆:首先應該知道操作系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時, 會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多余的那部分重新放入空閒鏈表中。

 

3.申請大小的限制

棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(vc編譯選項中可以設置,其實就是一個STACK參數,缺省2M),如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。

堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閒內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。

 

4.申請效率的比較:

棧:由系統自動分配,速度較快。但程序員是無法控制的。

堆:由malloc/new分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便.

 

5.堆和棧中的存儲內容

棧:在函數調用時,第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可執行語句)的地址,然後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然後是函數中的局部變量。注意靜態變量是不入棧的。

當本次函數調用結束後,局部變量先出棧,然後是參數,最後棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。

堆:一般是在堆的頭部用一個字節存放堆的大小。堆中的具體內容有程序員安排。

 

6.內存的回收

棧上分配的內存,編譯器會自動收回;堆上分配的內存,要通過free來顯式地收回,否則會造成內存洩漏。

堆和棧的區別可以用如下的比喻來看出:

使用棧就像我們去飯館裡吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等准備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。

使用堆就像是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。

 

十二、java的值傳遞和引用傳遞:

public StringgetPersonName(Person p){

return person.getName();

}

 

p變量裡面存放的是一個 堆內存裡面person對象的地址. (值). // 感覺java是只有值傳遞。

 

p變量他代表的是person對象的一個引用, 引用傳遞.

 

十三、多級指針:

例:使用r取到i的值:

#include

 

main(){

 

int i = 3;

int* p = &i;

 

int** q = &p;

 

 

int*** r = &q;

 

//取到i 的值

printf("i=%d\n",***r);

 

 

 

system("pause");

}

十三、函數的指針:

獲取函數的首地址,通過首地址,就可執行該函數。

 

例:

#include

/**

1.定義int (*pf)(int x, int y);

2.賦值 pf = add;

3.引用 pf(3,5);

*/

 

int add(int x, int y){

 

return x+y;

}

 

main(){

int (*pf)(int x,int y); // 定義一個函數的指針指針的類型是返回值為int 接受的參數 int

pf =add;

printf("result=%d\n", pf(3,6));

system("pause");

}

 

十四、結構體:使用struct 定義結構體:

 

#include

//定義一個結構體

struct Student

{

char sex; //1

int age; //4

float score; //4

int id; //4

};

 

main(){

//

struct Student st={80,55.6f,10000,'F' };

 

//獲取結構體的指針

struct Student* pst = &st;

 

printf("age=%d\n",st.age);

 

//結構體的長度

printf("結構體的長度%d\n",sizeof(st));

 

//通過指針獲取結構體中的變量

printf("age=%d\n", (*pst).age);

//通過指針獲取結構體中的變量 的第二種寫法:

printf("age=%d\n", pst->age);

system("pause");

}

 

十四、聯合體:

// 聯合體的作用是聲明一塊公用的內存空間,長度跟公用的數據類型中最長的一個條目一致,

當多次為同一個聯合體賦值時,會覆蓋:

 

 

#include

 

main( )

{

 

struct date { int year, month, day;}today;

union { long i; int k; char ii; } mix;

 

// 聯合體的作用是聲明一塊公用的內存空間

// 長度跟公用的數據類型中最長的一個條目一致

printf("date:%d\n",sizeof(struct date));

 

printf("mix:%d\n",sizeof(mix));

//下面的賦值,先定義的會被覆蓋。

mix.i = 99;

mix.k = 18;

mix.ii = 'A';

printf("i=%ld",mix.i);

 

system("pause");

}

十五、枚舉:

#include

enum WeekDay

{

Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday

};

 

int main(void)

{

//int day;

enum WeekDay day = Sunday;

printf("%d\n",day);

 

system("pause");

}

 

十六、typedef:

聲明自定義數據類型,配合各種原有數據類型來達到簡化編程的目的的類型定義關鍵字。

typedef int haha;//聲明一個int型的數據類型

 

例:

#include

typedef int haha;

int main(void)

{

haha i = 3;

printf("%d\n",i);

 

system("pause");

 

return 0;

}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved