C語言運(yùn)算符、表達(dá)式、聲明
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define M_PER_H 60 //聲明常量,每小時(shí)60分鐘
int conversion(int n); // 聲明函數(shù)原型,該函數(shù)需要一個(gè)int類型參數(shù)(形式參數(shù)parameter),返回int類型的值
void time_calculate(void);
void show_number(void);
int main(void)
{
int a1, a2, a3;
a1 = a2 = a3 = 5; // 三重賦值從右往左依次將5賦值給a3,將表達(dá)式a3=5賦值給a2,表達(dá)式a3=5的值等于左值a3的值,即(a3=5)的值是5,a2 = a3 = 5和a2 = (a3=5)等價(jià),而表達(dá)式a2=5的值為a2的值即5,賦值給a1,所以從右往左依次將a3、a2、a1的值賦值為5
a1 = 9 / a2; //整數(shù)除法會(huì)發(fā)生截?cái)?,結(jié)果為1,運(yùn)算的整個(gè)過程中并不會(huì)出現(xiàn)小數(shù),所以不存在四舍五入,結(jié)果永遠(yuǎn)是數(shù)學(xué)計(jì)算的結(jié)果截?cái)嘈?shù)的部分即商
a2 = -9 / a3; //存在負(fù)整數(shù)的整數(shù)除法同樣截?cái)嘈?shù),-1.8截?cái)嘧兂?1,c99標(biāo)準(zhǔn)稱為趨零截?cái)啵?.8截?cái)嘧兂?,正數(shù)負(fù)數(shù)都向零截?cái)?/span>
printf("%f\n", 9.0/a3); // 兩種類型以上的混合計(jì)算時(shí),程序會(huì)先進(jìn)行類型轉(zhuǎn)換,轉(zhuǎn)換成同類型之后再運(yùn)算,所以9.0/5變成9.0/5.0,結(jié)果為1.800000
printf("%zd\n", sizeof a1); //sizeof為運(yùn)算符而非函數(shù)
size_t a4 = 1; // size_t并非一種有別于int/long/unsigned等的新的數(shù)據(jù)類型,而是頭文件通過typedef聲明的某種類型的別名,在有些系統(tǒng)中將size_t設(shè)定為unsigned long int 的別名
typedef int in; // typedef 類型 別名? ,設(shè)定in為int的別名
in a5 = 1; // 定義in類型變量a5,因?yàn)樵O(shè)定in為int的別名,所以等價(jià)為int a5 = 1;
printf("%zd\n", sizeof a5); // a5同樣占4字節(jié),因?yàn)閷?shí)際類型是int
a1 = 5;
a2 = 3; //賦值表達(dá)式語句,=為賦值運(yùn)算符,將右側(cè)的值(右值)賦給左側(cè)的變量(左值)
a3 = a1 % a2; //求模運(yùn)算符%,即取a1除以a2的余數(shù)
a3 = a1 - (a1 / a2) * a2; //這個(gè)表達(dá)式和求模等價(jià),因?yàn)檎麛?shù)除法取商,所以a1/a2結(jié)果為1,用a1減去 商*a2 得到的就是余數(shù)
printf("%d\n", -9 % 5); // 用上面的表達(dá)式能夠解釋這一行的結(jié)果-4,由于趨零截?cái)啵?9/5結(jié)果為-1,所以-9-(-1*5)結(jié)果為-4,而9%-5的結(jié)果是4,余數(shù)永遠(yuǎn)和被除數(shù)(-9)同符號(hào),整數(shù)除法的趨零是結(jié)果截?cái)嘈?shù),求模的趨零是余數(shù)保持與被除數(shù)同符號(hào)取趨于零的最近數(shù)
while (a2++<5) // while循環(huán),()括號(hào)內(nèi)條件成立則執(zhí)行{}塊內(nèi)的內(nèi)容,循環(huán)判定()為true執(zhí)行{}的過程直到()為false向下執(zhí)行}后的內(nèi)容,a2++是指先使用a2再遞增+1
{ //執(zhí)行到這里時(shí)a2已經(jīng)遞增了
????printf("%d", a2); //結(jié)果為45
} // 即使最后一次判定時(shí)a2<5為false,在該語句while (a2++<5)括號(hào)結(jié)束之前C語言要求完成內(nèi)部所有運(yùn)算包括遞增賦值,所以即使a2<5為false,由于a2已經(jīng)使用過了,這時(shí)也會(huì)遞增1變?yōu)?
printf("\n%d\n", a2); //結(jié)果為6
a1 = 1;
a2 = 5 + a1++; //a1++指先使用a1再遞增,所以表達(dá)式中的a1代入1,a2為5+1即6,a1遞增變?yōu)?
a1--; // 遞減,a1的值變回1
a2 = (5 + a1++) * 2; //a1++指先使用a1再遞增,所以即便括起來,在表達(dá)式中的a1值也是1
printf("%d\t%d\n", a2, a1); //結(jié)果a2為(5+1)*2即12,a1為2
a1 = 1;
while (++a1<2)
{
????printf("++a1表示先遞增再使用,所以a1先變?yōu)?,再判斷<2false,所以這一條打印語句不會(huì)執(zhí)行");
}
a1 = 1;
a2 = 5 + (a1 = a1 + 2); //賦值表達(dá)式也有值,a1=a1+2使得a1變?yōu)?,但表達(dá)式(a1=a1+2)本身的值也是3,賦值表達(dá)式的值等于賦給左值/變量的值
printf("%d\n", a2);
a1 = 3;
while (++a1 <= 4)
????printf("%d\n", a1); //當(dāng)while語句的{}塊內(nèi)只有一個(gè)語句時(shí)可以省略{},寫成帶縮進(jìn)的形式便于閱讀,C語言不要求縮進(jìn)
char c1 = 5; //5為int常量,賦值給char時(shí)發(fā)生截?cái)?,只取最后一個(gè)字節(jié)的值,因?yàn)橹禌]有超過255所以結(jié)果仍然是正確的
printf("%f\n", c1 * 2 / 3.0); //表達(dá)式c1*2/3.0中出現(xiàn)三種類型,c1為char,2為int,3.0為double,執(zhí)行時(shí)根據(jù)優(yōu)先級(jí)及結(jié)合律逐漸轉(zhuǎn)換類型,char和short類型在表達(dá)式和函數(shù)傳參時(shí)會(huì)自動(dòng)轉(zhuǎn)換為int,int的5和int的2相乘結(jié)果為int的10,再和3.0運(yùn)算,運(yùn)算之前轉(zhuǎn)換為double的10.0/3.0
printf("%f\n", 2 / 3 * 4.0); //結(jié)果為0,因?yàn)橄冗\(yùn)算整數(shù)除法2/3趨零截?cái)嘟Y(jié)果為0,再和double的4.0運(yùn)算,所以結(jié)果為0
c1 = 1;
printf("%f\n", (float)c1 / 3 * 4); //在變量/常量之前使用(類型)強(qiáng)制轉(zhuǎn)型,1先強(qiáng)轉(zhuǎn)為1.0f再運(yùn)算,后面的int自動(dòng)轉(zhuǎn)為同類型float,結(jié)果作為double打印出來
//char/short出現(xiàn)在表達(dá)式或作為函數(shù)的參數(shù)時(shí)會(huì)自動(dòng)轉(zhuǎn)換為int,float在函數(shù)參數(shù)中會(huì)自動(dòng)轉(zhuǎn)換為double
double d1 = 1.0;
printf("%d\t", conversion(d1)); //函數(shù)conversion()的定義在下方,將double類型的d1傳給函數(shù),由于函數(shù)需要int類型的參數(shù),所以會(huì)發(fā)生類型強(qiáng)制轉(zhuǎn)換,傳的實(shí)參(實(shí)際參數(shù)argument)d1為1.0,經(jīng)過類型強(qiáng)制轉(zhuǎn)換后函數(shù)內(nèi)的形參n為1
// 結(jié)果為20,這里返回的是形參n的值
printf("%f\n", d1); //由于實(shí)參傳的并不是變量d1而是變量d1的值,所以無論函數(shù)內(nèi)發(fā)生什么變化,都不會(huì)對(duì)d1產(chǎn)生影響,d1仍然是1.0,函數(shù)接收實(shí)參1.0初始化形參n,實(shí)參是d1的值而不是d1
show_number();
return 0;
}
int conversion(int n) { //到這里時(shí)形參n的值仍然為實(shí)參傳進(jìn)來的int值
n = 20; // 這里改變了形參n的值,雖然用于初始化的實(shí)參/值沒有使用,但也不會(huì)改變主調(diào)函數(shù)變量d1本身
return n; //返回了形參n的值,形參的作用域到}括回結(jié)束
}
void time_calculate(void) {
int min = 0;
printf("分鐘轉(zhuǎn)換小時(shí)的程序\n請(qǐng)輸入分鐘(小于等于0退出程序):");
scanf("%d", &min);
while (min > 0) // 直到用戶輸入0或負(fù)數(shù)跳出循環(huán)
{
printf("%dmins = %dhours %dmins\n", min, min / M_PER_H, min % M_PER_H);
printf("請(qǐng)輸入分鐘(小于等于0退出程序):");
scanf("%d", &min); // 通過用戶輸入來迭代
}
printf("運(yùn)行結(jié)束");
const int D_PER_W = 7; // 使用const設(shè)定只讀變量,在初始化值之后不能進(jìn)行修改,只讀變量必須在聲明的語句內(nèi)進(jìn)行初始化,初始化不是賦值,不能分成兩個(gè)語句
}
void show_number(void) {
int num;
int count = 0;
printf("打印一個(gè)整數(shù)到其加10(包含)內(nèi)的所有整數(shù)\n輸入一個(gè)整數(shù):");
scanf("%d", &num);
while (++count <= 11) //通過++遞增來迭代,打印包頭包尾所以總共11個(gè)數(shù),count從1到11都判定true執(zhí)行11次循環(huán)
????printf("%3d ", num++); // num++先打印本身再遞增
printf("\n");
}
double temperatures() {
double n = 1.0;
const double SHE = 5.0 / 9.0;
printf("enter hua:");
while (scanf("%lf", &n) == 1) // 利用scanf()函數(shù)返回值(讀取數(shù)據(jù)的數(shù)量)作為循環(huán)條件,scanf使用%lf需要讀取一個(gè)double數(shù)字,如果讀取到數(shù)字則返回值為1,如果讀到第一個(gè)非空白字符為非數(shù)字字符,則不賦值并將該字符放回,并且停止執(zhí)行當(dāng)前scanf的后續(xù)讀?。ㄈ绻械脑挘@時(shí)由于沒有賦值/讀取到數(shù)字,賦值/讀取到的數(shù)據(jù)數(shù)量為0,條件為false退出循環(huán)
{
printf("hua:%.2f\tshe:%.2f\tkai:%.2f\n", n, SHE * (n - 32.0), SHE * (n - 32.0) + 273.16);
printf("enter hua:");
}
char str[20];
scanf("%s", str); //由于while循環(huán)的最后一次scanf()將非數(shù)字字符放回了輸入,所以現(xiàn)在輸入中還留有非空白字符,如果后續(xù)程序還需要讀取輸入,在往后進(jìn)行之前應(yīng)該將輸入清空
printf("%s", str);
scanf("%*s"); //scanf使用%*s實(shí)現(xiàn)只讀取不賦值,只是為了清理輸入隊(duì)列
}