C語(yǔ)言基礎(chǔ)
這是很簡(jiǎn)單的C語(yǔ)言氛堕,如果想深入了解,可以自己自學(xué)野蝇,C語(yǔ)言畢竟可以說(shuō)是高級(jí)編程語(yǔ)言的基礎(chǔ)呀讼稚,書(shū)籍一堆一堆的括儒。
我們要學(xué)習(xí)C語(yǔ)言,使用C語(yǔ)言開(kāi)發(fā)要怎么搞呢锐想?
首先就是一個(gè)必要的開(kāi)發(fā)工具帮寻,這里推薦開(kāi)源工具Dev-C++,一款用于編譯C語(yǔ)言的工具赠摇,就像eclipse開(kāi)發(fā)java一樣固逗,除了安裝Dev-C++之外,不在需要其他工具了藕帜。
C之Hello world
打開(kāi)Dev-C++工具烫罩,直接選擇新建或者快捷鍵CTRL+N新建一個(gè)C文件,然后我們輸入以下代碼:
#include<stdio.h>
#include<stdlib.h>
main(){
printf("helloworld!\n"); //System.out.println(); "\n"換行符
system("javac Hello.java");
system("java Hello");
system("notepad");
system("pause"); //system執(zhí)行windows的系統(tǒng)命令
}
然后保存到命名為C 的目錄中洽故,將文件保持為hello.c贝攒,但這只是一個(gè)原始代碼,繼續(xù)在Dev-C++中的菜單欄找到運(yùn)行时甚,然后選擇編譯隘弊,這時(shí)你會(huì)發(fā)現(xiàn)在hello.c的旁邊出現(xiàn)一個(gè)hello.exe。
哈荒适,是不是很神奇梨熙,我們自己搞出一個(gè)exe可執(zhí)行文件!
當(dāng)然我們現(xiàn)在還不用執(zhí)行hello.exe吻贿,我們要在C目錄下添加一個(gè)Hello.java(標(biāo)準(zhǔn)的java文件)的文件夾串结,里面輸入Hello,java就行了舅列。
這時(shí)執(zhí)行hello.exe肌割,就會(huì)打開(kāi)命令提示符,也就是CMD命令框帐要。
首先會(huì)輸入“helloworld!”把敞,然后編譯,接著執(zhí)行Hello.class榨惠,最后停止奋早。
這便是運(yùn)行流程。那么我們來(lái)說(shuō)說(shuō)文件中代碼的含義吧赠橙!
其中
#include<stdio.h> // 相當(dāng)于 java的import .h c的頭文件 stdio.h standard io 標(biāo)準(zhǔn)輸入輸出
#include<stdlib.h> // stdlib standard library 標(biāo)準(zhǔn)函數(shù)庫(kù) java.lang
在寫(xiě)C語(yǔ)言的時(shí)候添加上這兩句話準(zhǔn)沒(méi)錯(cuò)的耽装。
然后main(){ }這是一個(gè)主程序入口,就類似于java中的public static void main(String[] args)期揪。
最后就是system(),這相當(dāng)于system執(zhí)行windows的系統(tǒng)命令 掉奄,所以在執(zhí)行system("javac Hello.java");是相當(dāng)于我們?cè)诿钐崾痉兄苯虞斎雑avac Hello.java。
C語(yǔ)言的基本數(shù)據(jù)類型
前面我們已經(jīng)學(xué)會(huì)了C語(yǔ)言的Hello world凤薛,現(xiàn)在我們要了解一下C語(yǔ)言的數(shù)據(jù)類型了姓建,我們直接通過(guò)與java對(duì)比诞仓,看看他們直接有多大區(qū)別
java基本數(shù)據(jù)類型 所占字節(jié) C數(shù)據(jù)類型 所占字節(jié)
boolean 1
byte 1
char 2 char 1個(gè)字節(jié)
short 2 short 2
int 4 int 4
long 8 long 4
float 4 float 4
double 8 double 8
上面是java和C直接都有的數(shù)據(jù)類型,同時(shí)對(duì)比雙方所占字節(jié)數(shù)速兔,但是上面并不是C所有的數(shù)據(jù)類型墅拭,C一共有以下幾種數(shù)據(jù)類型:
char, int, float, double, long, short, signed, unsigned, void
* signed 有符號(hào)數(shù) 最高位是符號(hào)位 可以表示負(fù)數(shù) 但是表示的最大值相對(duì)要小
* unsigned 無(wú)符號(hào)數(shù) 最高位是數(shù)值位 不可以表示負(fù)數(shù) 表示的最大值相對(duì)要大
* signed unsigned 只能用來(lái)修飾整形變量 char short int long
* C沒(méi)有 boolean byte C用0和非0表示false true
上面我們了解C所占的字節(jié)數(shù),但是如何驗(yàn)證呢涣狗?可以通過(guò)以下代碼驗(yàn)證:
#include<stdio.h>
#include<stdlib.h>
// char, int, float, double, long, short, signed, unsigned, void
// signed unsigned 有符號(hào) 無(wú)符號(hào) 只能用來(lái)修飾整形變量 char int short long 默認(rèn)有符號(hào)
// sizeof(int)
main(){
printf("char占%d個(gè)字節(jié)\n", sizeof(char));
printf("int占%d個(gè)字節(jié)\n", sizeof(int));
printf("short占%d個(gè)字節(jié)\n", sizeof(short));
printf("float占%d個(gè)字節(jié)\n", sizeof(float));
printf("long占%d個(gè)字節(jié)\n", sizeof(long));
printf("double占%d個(gè)字節(jié)\n", sizeof(double));
unsigned char c = 128;
printf("c = %d\n",c);
system("pause");
}
其中%d表示的是int類型的占位符谍婉,請(qǐng)大家注意,在使用占位符的時(shí)候千萬(wàn)不要寫(xiě)錯(cuò)屑柔!然后sizeof(int)這個(gè)方法表示的是其中的變量所占的字節(jié)數(shù)屡萤。
占位符的使用
剛才說(shuō)到%d這個(gè)占位符珍剑,那么其他的占位符又是怎樣的呢掸宛?
%d - int
%ld – long int
%lld - long long
%hd – 短整型
%c - char
%f - float
%lf – double
%u – 無(wú)符號(hào)數(shù)
%x – 十六進(jìn)制輸出 int 或者long int 或者short int
%o - 八進(jìn)制輸出
%s – 字符串
以上就是C語(yǔ)言中的少數(shù)占位符,使用代碼如下:
#include<stdio.h>
#include<stdlib.h>
main(){
char c='a';
short s = 123;
int i = 12345678;
long l = 1234567890;
float f = 3.1415;
double d = 3.1415926;
printf("c = %c\n", c);
printf("s = %hd\n", s);
printf("i = %d\n",i);
printf("l = %ld\n",l);
printf("f = %.4f\n",f); //默認(rèn)輸出的是6位有效數(shù)字的小數(shù) 想手動(dòng)指定 加上.X
printf("d = %.7lf\n",d);
printf("%#x\n",i);
printf("% #o\n",i);
//char cArray[]={'a','b','c','d','\0'}; // C數(shù)組[]要寫(xiě)在變量名后面招拙, \0表示的是字符串結(jié)束符唧瘾,這種方式不能輸入漢字
//char cArray[]="abcdefg"; // 這種方式不用手動(dòng)寫(xiě)入結(jié)束符
char cArray[]="你好"; // 輸入漢字
printf("cArray = %s",cArray);
system("pause");
}
C語(yǔ)言之輸入函數(shù)
學(xué)習(xí)計(jì)算機(jī)語(yǔ)言逃不過(guò)一個(gè)宿命,那就是討論內(nèi)存地址别凤,而C語(yǔ)言中更是講究饰序。
在這里我們先通過(guò)鍵盤(pán)輸入班級(jí)人數(shù),然后通過(guò)取出count的地址來(lái)保存班級(jí)人數(shù)
#include<stdio.h>
#include<stdlib.h>
//scanf("占位符",內(nèi)存地址)
main(){
printf("請(qǐng)輸入班級(jí)的人數(shù):");
int count;
scanf("%d", &count); //&取地址符
printf("班級(jí)的人數(shù)是%d\n",count);
char cArray[20];//c的數(shù)組不檢測(cè)下標(biāo)越界
printf("請(qǐng)輸入班級(jí)的名字:");
scanf("%s",&cArray);
printf("班級(jí)的人數(shù)是%d,班級(jí)的名字%s\n",count,cArray);
printf("count的地址%d\n",&count);
printf("cArray的地址%d\n",&cArray);
system("pause");
}
C中的指針
C語(yǔ)言中的指針可以說(shuō)是一個(gè)重點(diǎn)難點(diǎn)规哪,比較難以理解求豫,因?yàn)槲覀儍?nèi)存地址讓人難以理解,所以這里只是拋磚引玉的粗略的講講指針的概念诉稍。
關(guān)于符號(hào)*
其中int* pointer 表示聲明一個(gè)int類型的指針變量pointer
x * y 表示乘法運(yùn)算
*pointer; 取出指針變量pointer 中保存的內(nèi)存地址對(duì)應(yīng)的內(nèi)存中的值
接著我們來(lái)看看指針的運(yùn)用:
#include<stdio.h>
#include<stdlib.h>
main(){
int i = 123;
//一般計(jì)算機(jī)中用16進(jìn)制數(shù)來(lái)表示一個(gè)內(nèi)存地址
printf("%#x\n",&i);
//int* int類型的指針變量 pointer指針 指針變量只能用來(lái)保存內(nèi)存地址
//用取地址符&i 把變量i的地址取出來(lái) 用指針變量pointer 保存了起來(lái)
//此時(shí)我們可以說(shuō) 指針pointer指向了 i的地址
int* pointer = &i;
//int *pointer ; int * pointer
printf("pointer的值 = %#x\n",pointer);
printf("*pointer的值%d\n",*pointer);
*pointer = 456;
printf("i的值是%d\n",i);
system("pause");
}
運(yùn)行這段代碼蝠嘉,會(huì)得到以下結(jié)果:
0x62fe44
pointer的值 = 0x62fe44
*pointer的值123
i的值是456
其中i的值為123,但是計(jì)算機(jī)給i分配一塊內(nèi)存地址既是0x62fe44這個(gè)空間杯巨,然后這個(gè)空間存放的值為123蚤告,這便是i=123的含義。
然后我們?cè)趧?chuàng)建了int類型的指針變量point服爷,當(dāng)然指針變量point也獲得了自己的一個(gè)內(nèi)存地址杜恰。
同時(shí)通過(guò)&i將i的內(nèi)存地址取出,賦予了point仍源,也就是說(shuō)指針變量point的內(nèi)存地址的值存入了0x62fe44這個(gè)內(nèi)存地址心褐,而通過(guò) 0x62fe44內(nèi)存地址是可以找到123這個(gè)值的。
那么如何在指針變量point中取出123呢笼踩?使用pointer便可以取出逗爹。
最后pointer = 456就是將0x62fe44這個(gè)內(nèi)存地址的值重新賦值為456,而i的內(nèi)存地址是指向0x62fe44的戳表,所以當(dāng)0x62fe44的值發(fā)生改變時(shí)桶至,i的值也隨之發(fā)生改變昼伴。
這里面有點(diǎn)繞,不好理解镣屹,但指針?lè)矫娴闹R(shí)確實(shí)要好好學(xué)習(xí)一下圃郊。
指針的錯(cuò)誤使用
在使用指針之前要注意對(duì)其進(jìn)行賦值,沒(méi)有賦值就進(jìn)行操作的指針被稱為野指針女蜈,在Windows中是不允許這樣操作的持舆,因此指針使用之前要初始化 賦給它一個(gè)自己程序中聲明的變量的地址
其次,指針使用的時(shí)候要注意 int類型的指針要指向int類型的內(nèi)存地址, double類型的指針要指向double類型的地址伪窖,如果亂指會(huì)出bug
下面是錯(cuò)誤的示例代碼:
#include<stdio.h>
#include<stdlib.h>
/**
*/
main(){
//注意逸寓,這是錯(cuò)誤的示例代碼
int i;
double d = 3.1415;
int* pointer = &d;
printf("pointer的值=%#x\n",pointer);
printf("*pointer = %d\n",*pointer);
system("pause");
}
C語(yǔ)言交換兩數(shù)的值
一個(gè)傳統(tǒng)的問(wèn)題,如何交換兩數(shù)的值覆山,以下代碼演示
#include<stdio.h>
#include<stdlib.h>
/**
*值傳遞 和引用傳遞 值傳遞和引用傳遞傳遞的實(shí)際上 都是數(shù)值 只不過(guò)引用傳遞傳遞的是地址值
*如果想通過(guò)一個(gè)子函數(shù)來(lái)修改main函數(shù)中變量的值 一定要用引用傳遞
*/
// 值傳遞
swap(int i, int j){
int temp = i;
i = j;
j = temp;
}
// 引用傳遞
swap2(int* pointer, int* pointer2 ){
int temp = *pointer;
*pointer = *pointer2;
*pointer2 = temp;
}
main(){
int i = 123;
int j = 456;
// swap(i,j); // 無(wú)法交換兩數(shù)的值
swap2(&i,&j); // 通過(guò)交換內(nèi)存地址中的值竹伸,成功交換兩數(shù)的值
printf("i的值%d,j的值%d\n",i,j);
system("pause");
}
為什么swap方法無(wú)法交換i和j的值呢?舉個(gè)不恰當(dāng)?shù)睦哟乜恚沁吺蔷植孔兞亢统蓡T變量的區(qū)別勋篓,首先swap外部有i和j,然后傳入swap之后魏割,i和j便與外部的i和j斷絕了關(guān)系譬嚣,因此在內(nèi)部交換之后無(wú)法將交換信息傳遞到外部。
而swap2采用的是引用傳遞钞它,通過(guò)獲取內(nèi)存地址拜银,改變內(nèi)存地址之中的值,這時(shí)才能真正的改變兩數(shù)的值
c中數(shù)組與指針的關(guān)系
數(shù)組實(shí)際上就是一塊連續(xù)的內(nèi)存空間遭垛,而數(shù)組變量名的地址實(shí)際上是第一個(gè)元素的地址尼桶,因此我們通過(guò)指針獲取數(shù)組變量名的內(nèi)存地址,可以說(shuō)是獲得了數(shù)組的內(nèi)存地址耻卡。
同時(shí)我們通過(guò)對(duì)內(nèi)存地址的加減法就能獲得數(shù)組中的元素疯汁。需要注意的是對(duì)內(nèi)存地址的加減法中,相加得到的結(jié)果實(shí)質(zhì)上與數(shù)據(jù)類型有關(guān)卵酪,如我們使用指針變量*(pointer+0)幌蚊,如果是int類型的數(shù)組,實(shí)質(zhì)上會(huì)加上4個(gè)字節(jié)溃卡,得到下一個(gè)數(shù)組元素溢豆,char類型的數(shù)組也是一樣
#include<stdio.h>
#include<stdlib.h>
main(){
// char array[] = {'a','b','c','d','\0'};
int array[] = {1,2,3,4};
printf("array[0]的地址%#x\n",&array[0]);
printf("array[1]的地址%#x\n",&array[1]);
printf("array[2]的地址%#x\n",&array[2]);
printf("array[3]的地址%#x\n",&array[3]);
printf("array的地址%#x\n",&array);
//數(shù)組變量名的地址實(shí)際上是第一個(gè)元素的地址
char* pointer = &array;
//int* pointer = &array;
char array2[] = "hello from c"
char* pointer2="hello from c";
//printf("%s\n",pointer2);
/*
// char類型中每次運(yùn)算是相加1個(gè)字節(jié)
printf("*(pointer+0)=%c\n",*(pointer+0));
printf("*(pointer+0)=%c\n",*(pointer+1));
printf("*(pointer+0)=%c\n",*(pointer+2));
printf("*(pointer+0)=%c\n",*(pointer+3));
*/
// 在int類型數(shù)組中,指針變量每次運(yùn)算結(jié)果是相加4個(gè)字節(jié)
printf("*(pointer+0)=%d\n",*(pointer+0));
printf("*(pointer+1)=%d\n",*(pointer+1));
printf("*(pointer+2)=%d\n",*(pointer+2));
printf("*(pointer+3)=%d\n",*(pointer+3));
system("pause");
}
C語(yǔ)言中指針變量的字節(jié)數(shù)
指針變量的所占字節(jié)數(shù)與所指向的數(shù)據(jù)類型無(wú)關(guān)瘸羡,與操作系統(tǒng)有關(guān)漩仙,32位操作系統(tǒng)地址總線是32位,用4個(gè)字節(jié)的變量來(lái)保存32位操作系統(tǒng)的內(nèi)存地址 1byte 8位 4*8=32
因此32位操作系統(tǒng) 指針變量占4個(gè)字節(jié),而64位操作系統(tǒng) 指針變量占8個(gè)字節(jié) 队他。
#include<stdio.h>
#include<stdlib.h>
/**
32位操作系統(tǒng)地址總線是32位 4個(gè)字節(jié)的變量來(lái)保存32位操作系統(tǒng)的內(nèi)存地址 1byte 8位 4*8=32
32位操作系統(tǒng) 指針變量占4個(gè)字節(jié)
64位操作系統(tǒng) 指針變量占8個(gè)字節(jié)
*/
main(){
int* pointer;
double* pointerD;
printf("int類型的指針變量占%d個(gè)字節(jié)\n",sizeof(pointer));
printf("double類型的指針變量占%d個(gè)字節(jié)\n",sizeof(pointerD));
system("pause");
}
C語(yǔ)言之多級(jí)指針
多級(jí)指針:數(shù)星星卷仑,有幾個(gè)星就是幾級(jí)指針。其中二級(jí)指針只能保存一級(jí)指針的內(nèi)存地址麸折,同意三級(jí)指針只能保存二級(jí)指針的內(nèi)存地址锡凝。
那么如果想通過(guò)三級(jí)指針拿到最初的變量的值,就使用 ***point3
#include<stdio.h>
#include<stdlib.h>
main(){
int i = 123;
//int類型的一級(jí)指針
int* pointer = &i;
//int類型的二級(jí)指針 二級(jí)指針只能保存一級(jí)指針的地址
int** pointer2 = &pointer;
//int類型的三級(jí)指針
int*** pointer3 = &pointer2;
// 取出初始值
printf("***pointer3 = %d\n",***pointer3);
system("pause");
}
C主函數(shù)獲取臨時(shí)變量的地址
main函數(shù)獲取子函數(shù)中臨時(shí)變量的地址垢啼,此時(shí)要注意值傳遞和引用傳遞的區(qū)別窜锯,我們想要獲得的是內(nèi)存地址,因此必須傳入內(nèi)存地址芭析,同時(shí)二級(jí)指針才能保存一級(jí)指針的內(nèi)存地址锚扎,因此子函數(shù)中要傳入的變量應(yīng)為二級(jí)指針
#include<stdio.h>
#include<stdlib.h>
function(int** pointer){
int i = 123;
*pointer = &i;
printf("i的地址%#x\n",&i);
}
main(){
int* pointer1;
function(&pointer1);
printf("pointer1的值%#x\n",pointer1);
system("pause");
}
C語(yǔ)言中的內(nèi)存地址回收
棧內(nèi)存由系統(tǒng)統(tǒng)一分配統(tǒng)一回收
靜態(tài)內(nèi)存分配 棧內(nèi)存大小固定的 內(nèi)存地址是連續(xù)的
#include<stdio.h>
#include<stdlib.h>
int* getData(){
int array[] ={1,2,3,4,5};
printf("%#x\n",&array);
return &array;
}
int* getData2(){
int array[] ={5,4,3,2,1};
printf("%#x\n",&array);
return &array;
}
main(){
int* pointer = getData();
getData2();
printf("%d,%d,%d\n",*(pointer+0),*(pointer+1),*(pointer+2));
printf("%d,%d,%d\n",*(pointer+0),*(pointer+1),*(pointer+2));
printf("%#x\n",pointer);
system("pause");
}
在這一例子中,pointer指向的是getData()中的內(nèi)存地址馁启,可是為什么得到的結(jié)果卻是getData2()的值呢驾孔?那是因?yàn)樵趫?zhí)行完getData()之后,獲得的棧內(nèi)存地址被回收进统,然后直接被getData2()使用助币,導(dǎo)致其中的值被修改。所以使用指針的時(shí)候要注意螟碎,棧內(nèi)存只能使用一次,之后會(huì)出現(xiàn)同一塊內(nèi)存地址被其他程序占用的情況迹栓。如果想讓內(nèi)存始終保持一個(gè)只掉分,那么則要使用堆內(nèi)存
c中的動(dòng)態(tài)內(nèi)存分配
java new對(duì)象就會(huì)申請(qǐng)一塊堆內(nèi)存,而C語(yǔ)言則要手動(dòng)申請(qǐng)克伊,使用malloc申請(qǐng)一個(gè)固定的內(nèi)存大小酥郭,如malloc(sizeof(int)*5)申請(qǐng)5個(gè)int類型大小的內(nèi)存,注意申請(qǐng)了堆內(nèi)存需要手動(dòng)釋放愿吹,如果忘記釋放容易造成內(nèi)存泄漏不从。
其中對(duì)內(nèi)存的特點(diǎn):不連續(xù)的;大小不固定犁跪,取決機(jī)器的狀態(tài)
#include<stdio.h>
#include<stdlib.h>
//c malloc memory allocation 內(nèi)存分配
main(){
//malloc 接收的參數(shù) 申請(qǐng)內(nèi)存大小 返回一個(gè)內(nèi)存地址值 申請(qǐng)到的也是一塊連續(xù)的內(nèi)存空間
int* pointer = malloc(sizeof(int)*5);
*(pointer+0) = 1;
*(pointer+1) = 2;
*(pointer+2) = 3;
*(pointer+3) = 4;
*(pointer+4) = 5;
//C for 循環(huán) 循環(huán)的臨時(shí)變量i 要先聲明再使用
int i;
for(i = 0;i<5;i++){
printf("第%d個(gè)元素的值= %d\n",i,*(pointer+i));
}
free(pointer);
printf("第一個(gè)元素的值%d\n",*(pointer+0));
system("pause");
}
學(xué)生學(xué)號(hào)管理系統(tǒng)
#include<stdio.h>
#include<stdlib.h>
/**
保存班級(jí)人數(shù)
申請(qǐng)一塊堆內(nèi)存保存學(xué)生的學(xué)號(hào)
來(lái)了幾個(gè)插班生
擴(kuò)展一下堆內(nèi)存
保存插班生的學(xué)號(hào)
realloc re-
*/
main(){
printf("請(qǐng)輸入班級(jí)的人數(shù):");
int count;
scanf("%d",&count);
//申請(qǐng)一塊堆內(nèi)存
int* pointer = malloc(sizeof(int)*count);
int i;
for(i = 0;i<count;i++){
printf("請(qǐng)輸入第%d個(gè)學(xué)生的學(xué)號(hào):",i+1);
scanf("%d", pointer+i);
}
for(i = 0;i<count;i++){
printf("第%d個(gè)學(xué)生的學(xué)號(hào)是:%d\n",i+1,*(pointer+i));
}
printf("請(qǐng)輸入插班生的人數(shù):");
//聲明一個(gè)變量increment用來(lái)保存 插班生的人數(shù)
int increment;
//接受用戶的輸入
scanf("%d",&increment);
//重新申請(qǐng)一塊足夠大的內(nèi)存
//如果 malloc申請(qǐng)到的內(nèi)存后面還有足夠的空間 realloc會(huì)在malloc申請(qǐng)的內(nèi)存空間后繼續(xù)申請(qǐng)足夠大的內(nèi)存空間
//如果 malloc申請(qǐng)到的內(nèi)存后面沒(méi)有足夠的空間 realloc會(huì)找到一塊足夠大的堆內(nèi)存 并且把 malloc申請(qǐng)到的內(nèi)存中的值復(fù)制過(guò)來(lái)
pointer = realloc(pointer,sizeof(int)*(count+increment));
for(i = count;i<count+increment;i++){
printf("請(qǐng)輸入第%d個(gè)學(xué)生的學(xué)號(hào):",i+1);
scanf("%d", pointer+i);
}
for(i = count;i<count+increment;i++){
printf("第%d個(gè)學(xué)生的學(xué)號(hào)是:%d\n",i+1,*(pointer+i));
}
system("pause");
}
C的結(jié)構(gòu)體
c結(jié)構(gòu)體類似java的class椿息,使用struct來(lái)聲明c的結(jié)構(gòu)體。
結(jié)構(gòu)體的大小大于等于結(jié)構(gòu)體中每一變量的占字節(jié)數(shù)的和坷衍,
結(jié)構(gòu)體的大小是最大的那個(gè)變量所占字節(jié)數(shù)的整數(shù)倍寝优。如果想獲得結(jié)構(gòu)體中的變量,可通過(guò)獲取結(jié)構(gòu)體指針枫耳,然后通過(guò)結(jié)構(gòu)體指針獲得結(jié)構(gòu)體變量
注意C結(jié)構(gòu)體中不能定義函數(shù)乏矾,如果想要在結(jié)構(gòu)體中調(diào)用方法,可以使用函數(shù)指針。
函數(shù)指針的定義的方式:返回值(函數(shù)指針變量名字)(返回值)钻心,如下面示例代碼中的void(studypointer)();
其中 -> 表示間接引用運(yùn)算符凄硼,可以訪問(wèn)結(jié)構(gòu)體里面的變量,如示例代碼中的stuPointer->age
結(jié)構(gòu)體的特點(diǎn)
- 結(jié)構(gòu)體中的屬性長(zhǎng)度會(huì)被自動(dòng)補(bǔ)齊捷沸,這是為了方便指針位移運(yùn)算
- 結(jié)構(gòu)體中不能定義函數(shù)帆喇,可以定義函數(shù)指針
- 程序運(yùn)行時(shí),函數(shù)也是保存在內(nèi)存中的亿胸,也有一個(gè)地址
- 結(jié)構(gòu)體中只能定義變量
- 函數(shù)指針其實(shí)也是變量坯钦,它是指針變量
- 函數(shù)指針的賦值: 函數(shù)指針只能指向跟它返回值和接收的參數(shù)相同的函數(shù)
#include<stdio.h>
#include<stdlib.h>
void study(){
printf("good good study!\n");
}
struct Student{
int age; //8
int score; // 4
char sex; //1
void(*studypointer)();
} ;
main(){
struct Student stu = {18,100,'f'};
stu.studypointer = &study;
stu.studypointer();
struct Student* stuPointer = &stu;
printf("*stuPointer.age = %d\n",(*stuPointer).age);
(*stuPointer).sex ='m';
printf("stu.sex = %c\n",stu.sex);
printf("stuPointer->age = %d",stuPointer->age);
//printf("stu.age = %hd\n",stu.age);
//printf("stu.score = %d\n",stu.score);
//printf("stu.sex = %c\n",stu.sex);
// printf("結(jié)構(gòu)體student占%d個(gè)字節(jié)\n",sizeof(stu));
system("pause");
}
C中的聯(lián)合體
聯(lián)合體占字節(jié)數(shù)取決于,其中成員占內(nèi)存空間最大的那一個(gè) 侈玄。
聯(lián)合體只能保存一個(gè)變量的值婉刀,并且聯(lián)合體共用同一塊內(nèi)存。
#include<stdio.h>
#include<stdlib.h>
/**
*/
union u{
int num; //4個(gè)字節(jié)
double d; //8個(gè)字節(jié)
}
main(){
union u u1;
u1.num = 123;
u1.d = 123.456;
printf("union占%d個(gè)字節(jié)\n",sizeof(u1));
printf("u1.num = %d\n",u1.num);
system("pause");
}
C中的枚舉
C中的枚舉使用enum序仙,同時(shí)枚舉中的元素可賦值
#include<stdio.h>
#include<stdlib.h>
/**
*/
enum weekday{
MON=9, TUE, WEND,THUR,FRI,SAT,SUN
};
main(){
enum weekday day = MON;
printf("day= %d",day);
system("pause");
}
C中的自定義類型
自定義類型使用typedef可給類型賦予別名突颊,如 typedef int i;此時(shí)能將i當(dāng)作int類型使用。
用途:如果結(jié)構(gòu)體名字過(guò)長(zhǎng)潘悼,可起到省略的作用律秃,其中在Android的jni中大量使用了typedef設(shè)置別名,便于辨認(rèn)數(shù)據(jù)類型
// 簡(jiǎn)單實(shí)例:
#include<stdio.h>
#include<stdlib.h>
/**
*/
typedef int i;
main(){
i j = 123;
printf("j = %d\n",j);
system("pause");
}
如在之前的結(jié)構(gòu)體中有
struct Student{
···
} ;
可更改為:
typedef struct Student{
int age; //8個(gè)字節(jié)
int score; // 4個(gè)字節(jié)
char sex; //1個(gè)字節(jié)
// 使用函數(shù)指針調(diào)用函數(shù)
void(*studypointer)();
} stud;
此時(shí)在main函數(shù)中就可以直接使用stud代替Student治唤,如下:
main(){
stud stu = {18,100,'f'};
// 函數(shù)指針指向函數(shù)的內(nèi)存地址
stu.studypointer = &study;
····
}