当前位置:文档之家› C语言高级用法学习笔记

C语言高级用法学习笔记

C语言高级用法学习笔记
C语言高级用法学习笔记

1.#得作用

#就是将其后得变量直接转换为字符串

void WriteLog(arg)

{

printf("%s=%d",#arg,arg)

}

2.##得作用

##得作用就是连接两个变量

#define combine_converse_str(x,y) x##y

int Err;

int Num;

printf("%s",combine_converse_str(Err,Num));

结果为:ErrNum

再如:

int a=1;

int b=2;

int ab=3;

printf("%d",a##b);

结果为: 3

后面那句相当于printf("%d",ab);

3.d o{ }while(0)作用

1,空得宏定义避免warning:

#define foo() do{}while(0)

2,存在一个独立得block,可以用来进行变量定义,进行比较复杂得实现。

3,用在宏定义上并且当宏定义需要定义成多条语句得组合时,可以保证这几条语句就是一个整体得,并且可以消除使用这个宏定义后添加";"所带来得报错,例如:

#define aaa(x,y) \

do{ \

int a=0; \

int b=0; \

函数1(x); \

函数2(y); \

}while(0)

调用aaa(x,y); 时不会报错并且如果使用:

if (m)

aaa(1,2);

else

aaa(3,4);

时运行也不会使某些语句没有被运行到。

4.数组名得使用

数组名作为函数参数:数组名用在某个函数A得参数中时,处于函数传递效率原因,会被强制转换成了指针,此后在函数A内就完全就是一个值等于对应数组首地址得指针变量,可自加自减等

注意!只有在作为函数参数得情况下才会将数组名强制转换成指针,其她得都不会转换。

另:数组名作为函数参数传递时,函数声明得写法有多种

int aaa(char x[])

int aaa(char x[1])

int aaa(char x[100])

int aaa(char *x)

作为函数参数时得参数声明也与普通得数组定义一样要合法,比如不能int aaa(char x[0]),因为定义一个数组也不能用char x[0]来定义,编译器在检查参数得声明合法后,如果发现参数就是数组,就会强制转换成指针,所以int aaa(char x[1])与int aaa(char x[100])得结果就是一样得。

B.数组名用在sizeof上:结果返回得就是整个数组所占空间得大小,而不就是一个指针得长度

数组名与&与*:a与&a与&a[0]得值都相等,a就是数组名,&a就是整个数组地址,&a[0]就是数组首元素得地址,她们都相等

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

printf("a=%x\n",a);

printf("&a=%x\n",&a);

printf("*&a=%x\n",*&a);

printf("&a[0]=%x\n",&a[0]);

printf("*&a[0]=%x\n",*&a[0]);

printf("*(&a[0])=%x\n",*(&a[0]));

printf("*((int *)(&a))=%x\n",*((int *)(&a)));

printf("*(*(&a))=%x\n",*(*(&a)));

结果:

a=12ff34

&a=12ff34

*&a=12ff34 ---*与&消掉,*&a=a=0x12ff34

&a[0]=12ff34

*&a[0]=1 ---*与&消掉,*&a[0]=a[0]=1

*(&a[0])=1 ---*与&消掉,*(&a[0])=*&a[0]=a[0]=1

*((int *)(&a))=1 ---*与&之间有个强制类型转换(int *),无法直接消掉,所

以按照括号次序来运算(int *)(&a)=0x12ff34, *((int *)(&a))=*(0x12ff34)=1

*(*(&a))=1 ---*与&消掉,*(*(&a))=*a=1

D.指针数组:

定义:基类型 *数组名[]

使用:像普通得数组一样使用,数组名代表首地址,数组名[0]表示第一个元素得内容,以此类推。

常见得就是字符串数组,例如:

char *Names[]=

{

Bill,

Sam,

Jim

};为汇颖齜鳴骐鈧。

实际内存中保存得就就是

即首地址0x12ff0c{0x00423018,0x0042f2f4,0042201c},其中0x00423018地址所保存得就就是”Bill”,所以数组名Name=0x12ff0c, &Name=0x12ff0c,*Name=0x00423018,**Name=0x42

printf("Name=%x\n",Name);

printf("&Name=%x\n",&Name);

printf("*&Name=%x\n",*&Name);

printf("&Name[0]=%x\n",&Name[0]);

printf("*Name=%x\n",*Name);

printf("**Name=%x\n",**Name);

printf("Name[0]=%x\n",Name[0]);

printf("*Name[0]=%x\n",*Name[0]);

printf("*&Name[0]=%x\n",*&Name[0]);

printf("*(&Name[0])=%x\n",*(&Name[0]));

printf("(*((int *)(&Name)))=%x\n",(*((int *)(&Name))));

printf("(*(*(&Name)))=%x\n",(*(*(&Name))));

结果就是

Name=&Name=*&Name=&Name[0]=0x12ff0c

*Name=Name[0]=*&Name[0]=*(&Name[0])=(*((int

*)(&Name)))=(*(*(&Name)))=0x00423018

**Name=*Name[0]=0x42

注意!指针就是一级,数组就是又一级,所以指针数组就是二级指针,定义对应得指针变量要用二级指针,比如int **p=Name; 不能直接用int *p=Name

5.常量得定义与指针常量得定义及使用:

1、常量得定义:

const int a=10; //在其她地方不允许修改a得值,否则会编译不通过、

也可以写成int const a=10; //一样得

2、指针常量得定义与使用:

有3种定义: const int *pi; 与int const *pi; 以及int * const pi;

1)前两种情况一样得,没有区别。

1) 如果const 修饰在*pi前(前2种情况)则不能改得就是*pi(即不能类似这样:*pi=50;赋值)而不就是指pi、

2) 如果const 就是直接写在pi前(后一种情况)则pi不能改(即不能类似这样:pi=&i;赋值)。

6.函数参数传递得4种类型:

1、值传递

void Exchg1(int x, int y)

{

int tmp;

tmp = x;

x = y;

y = tmp;

printf("x = %d, y = %d\n", x, y);

}

main()

{

int a = 4,b = 6;

Exchg1(a, b);

printf("a = %d, b = %d\n", a, b);

return(0);

}

2、地址传递

void Exchg2(int *px, int *py)

{

int tmp = *px;

*px = *py;

*py = tmp;

printf("*px = %d, *py = %d、\n", *px, *py);

}

main()

{

int a = 4;

int b = 6;

Exchg2(&a, &b);

printf("a = %d, b = %d、\n", a, b);

return(0);

}

3、引用传递

void Exchg3(int &x, int &y)

{

int tmp = x;

x = y;

y = tmp;

printf("x = %d,y = %d\n", x, y);

}

main()

{

int a = 4;

int b = 6;

Exchg3(a, b);

printf("a = %d, b = %d\n", a, b);

return(0);

}

4、变长参数传递:使用省略号…指定参数表

使用得宏及其定义(x86中):

#define va_start _crt_va_start

#define va_arg _crt_va_arg

#define va_end _crt_va_end

typedef char * va_list;

#define _ADDRESSOF(v) ( &(v) )

#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) #define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) #define _crt_va_end(ap) ( ap = (va_list)0 )

实例:

#include "stdafx、h"

#include "stdio、h"

#include "string、h"

#include "stdarg、h"

/*至少需要一个确定得参数,注意括号内得省略号*/

int demo(char *fmt, 、、、)

{

va_list argp;

int argno = 0;

char *para;

va_start(argp, fmt);

while (1)

{

para = va_arg(argp, char *);

if (strcmp(para, "") == 0)

break;

printf("Parameter #%d is: %s\n", argno, para);

argno++;

}

va_end(argp);

return 0;

}

int main()

{

demo("DEMO1", "This", "is", "a", "demo!", "");

return 0;

}

运行结果:

详解:

1.函数得参数与局部变量都就是存储在栈里

栈得内存分配就是按从高地址到低地址分配得(而其她得正常就是从小到大分配,比如全局变量定义等),即先分配高地址得,再分配低地址得内存

所有得函数参数(不管就是定长参数还就是变长参数)入栈都就是从右到左入栈,如调函数a(x,y,z), 则z先入栈,并存在栈底(高地址),其次y,其次x。

4.数据在内存里得存储默认都按照字节对齐来存储(x86按照4字节对齐),如:

int aaa(char a, char b, char c)

{

return (int)(a+b+c);

}

调用函数aaa(5,6,7);时,内存中就是这样得:

所以,如果就是数值,则会直接存储在栈中,如果就是指针类型(如字符串),则会把指针值(即字符串首地址得值)存储在栈中,从右到左依次按照从高地址到低地址存储。

如实例得程序调用demo("DEMO1", "This", "is", "a", "demo!", "");得到得堆栈为:

即0x0012FEFb开始往低地址方向得部分为此函数得栈空间,存入得值分别为0x00422038,0x00422058,0x0042204C,0x00422034,0x00422044,0x0042203C,这6个地址分别所指向得实际上就就是静态存储区存储””,"demo!", "a", "is","This","DEMO1"得地方,见图

另:如果改成demo("DEMO1", 1, 2, "a", "demo!", "");则其中得数字1,2直接保存在栈中,见图

#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

得运算结果实际上就就是当1<=sizeof(n)<=4时取4,5<=sizeof(n)<=8时取8……即4得倍数

其结果实际上就就是一个参数所占得空间大小,所以每次调用va_arg取参数时,va_arg 里只需移动_INTSIZEOF(n)长度就对了。

所以实际上变长参数得实现原理很简单,不过要注意一点,就就是由于没有哪个地方表明栈中保存这些参数得长度就是多少,所以其实调用va_arg逐个取里面得参数时,就是

不知道取多少得,所以需要:

1)、从demo(n,…)得第一个已知参数n传入,例如demo(4,1,2,3,4)

2)、或者从demo(string,…)得string中利用格式化字符串来间接标识后面有多少个参数,

例如demo(“test1=%s,test2=%d”,str,i) 通过判断%得个数来得到要调用2遍va_arg(其实这种有种简便得方法就就是调用va_start后直接使用sprintf或者vsprintf或者vnsprintf 来打印格式化得字符串)

3)、或者通过实例中那样最后一个用\0来标识

4)、或者还有其她得方法,总之需要有所标识

然后再在函数里做相应判断,使va_arg得调用次数正确。

总说明:

1.地址传递得实质也就是值传递,只就是通过地址来可以对实参进行操作;

引用传递就就是在定义函数得时候各参数加一个&取地址符号,其她得都跟值传递一样使用,同样可以改变实参变量得内容。引用传递实际上跟地址传递过程就是一样得,只就是函数压栈得时候由于函数(以引用参数部分得实例为例)得参数定义为void Exchg3(int &x, int &y),所以就告诉编译器压栈就是要压调用者Exchg3(a, b);实参a,b得地址,即&a与&b,而在void Exchg3(int &x, int &y)函数内部使用得时候就是用x与y,即*(&x)与*(&y),所以其实就是与地址传递完全一样得,只就是换了一种表达形式而已,编译成汇编语言后就是一模一样得。

函数参数传递过程就是在一个新得栈空间中对实参进行压栈,然后在函数内部读取这些栈内得数据得过程,只不过如果在函数定义时参数就是数值型得话(例如值传递得int aaa(int a, int b, int c))就将这个参数得值压栈,如果在函数定义时参数就是地址型得话(例如地址传递int aaa(int *a,int *b)与引用传递int aaa(int &a, int &b))就将地址值压栈。

所谓在新得栈空间中压栈实质就就是把当前需要压栈得数值或地址按照一定次序拷贝到新得栈空间中。

附:函数压栈过程与汇编程序对应解析

传值方式C语言代码:

void changefunc(char a, char b)

{

char temp;

temp=a;

a=b;

b=temp;

}

int main()

{

char x=5,y=6;

changefunc(x,y);

demo("DEMO1", 1, 2, "a", "demo!", "");

return 0;

}

编译成汇编对应得代码:

8: {

0040D880 push ebp ---步骤5、将ebp得值0x0012ff48压栈,此语句执行后esp=0x0012fee4=M-0x10,ebp=0x0012ff48

0040D881 mov ebp,esp ---步骤6、此语句执行后esp=0x0012fee4=M-0x10,ebp=0x0012fee4

0040D883 sub esp,44h ---步骤7、此语句执行后esp=0x0012fea0=M-0x54,ebp=0x0012fee4 44h为编译器预留得栈空间,提供函数内申请局部变量等使用(这个值得大小编译器会自动根据实际函数使用空间来定,无需上层干涉)

0040D886 push ebx ---步骤8、此语句执行后esp=0x0012fe9c=M-0x58,ebp=0x0012fee4

0040D887 push esi ---步骤9、此语句执行后esp=0x0012fe98=M-0x5c,ebp=0x0012fee4

0040D888 push edi ---步骤10、此语句执行后esp=0x0012fe94=M-0x60,ebp=0x0012fee4

0040D889 lea edi,[ebp-44h]

0040D88C mov ecx,11h

0040D891 mov eax,0CCCCCCCCh

0040D896 rep stos dword ptr [edi]

9: char temp;

10: temp=a;

0040D898 mov al,byte ptr [ebp+8]

0040D89B mov byte ptr [ebp-4],al

11: a=b;

0040D89E mov cl,byte ptr [ebp+0Ch]

0040D8A1 mov byte ptr [ebp+8],cl

12: b=temp;

0040D8A4 mov dl,byte ptr [ebp-4]

0040D8A7 mov byte ptr [ebp+0Ch],dl

13: }

0040D8AA pop edi ---步骤11、此语句执行后esp=0x0012fe98=M-0x5c,ebp=0x0012fee4

0040D8AB pop esi ---步骤12、此语句执行后esp=0x0012fe9c=M-0x58,ebp=0x0012fee4

0040D8AC pop ebx ---步骤13、此语句执行后esp=0x0012fea0=M-0x54,ebp=0x0012fee4

0040D8AD mov esp,ebp ---步骤14、此语句执行后esp=0x0012fee4=M-0x10,ebp=0x0012fee4

0040D8AF pop ebp ---步骤15、此语句执行后esp=0x0012fee8=M-0xc,ebp=0x0012ff48

0040D8B0 ret ---步骤16、此语句执行后esp=0x0012feec=M-0x8,ebp=0x0012ff48

33: int main()

34: {

004010F0 push ebp

004010F1 mov ebp,esp

004010F3 sub esp,48h

004010F6 push ebx

004010F7 push esi

004010F8 push edi

004010F9 lea edi,[ebp-48h]

004010FC mov ecx,12h

00401101 mov eax,0CCCCCCCCh

00401106 rep stos dword ptr [edi]

35: char x=5,y=6;

00401108 mov byte ptr [ebp-4],5

0040110C mov byte ptr [ebp-8],6

36: changefunc(x,y); ---步骤1、此时esp=0x0012fef4,ebp=0x0012ff48 记0x0012fef4值为M

00401110 mov al,byte ptr [ebp-8]

00401113 push eax ---步骤2、将y得值6压栈,此语句执行后esp=0x0012fef0=M-4,ebp=0x0012ff48

00401114 mov cl,byte ptr [ebp-4]

00401117 push ecx ---步骤3、将x得值5压栈,此语句执行后esp=0x0012feec=M-8,ebp=0x0012ff48

00401118 call @ILT+65(changefunc) (00401046) ---步骤4、行00401046就是一条跳转语句jmp changefunc(0040D880) ,压入返回地址,所以跳转后esp=0x0012fee8=M-0xc,ebp=0x0012ff48

0040111D add esp,8 ---步骤17、因为call changefunc函数之前有2个参数压栈,所以要恢复此前得esp,就需要加上2*4,此语句执行后esp=0x0012fef4=M,ebp=0x0012ff48

37: demo("DEMO1", 1, 2, "a", "demo!", "");

00401120 push offset string "" (00422038)

00401125 push offset string "demo!" (00422058)

0040112A push offset string "This" (00422044)

0040112F push 2

00401131 push 1

00401133 push offset string "DEMO1" (0042203c)

00401138 call @ILT+5(demo) (0040100a)

0040113D add esp,18h

38: return 0;

00401140 xor eax,eax

39: }

00401142 pop edi

00401143 pop esi

00401144 pop ebx

00401145 add esp,48h

00401148 cmp ebp,esp

0040114A call __chkesp (00401270)

0040114F mov esp,ebp

00401151 pop ebp

00401152 ret

7.E BP与ESP

EBP Extend base pointer: 用于存取栈得指针

ESP Extend stack pointer:栈顶指针

ESP就就是一直指向栈顶得指针,而EBP只就是存取某时刻得栈顶指针地址按照从小到大排列,压栈都就是从高地址从低地址压栈,

高地址

8.多个字符串可以直接连在一起写

如:

#define PRINT(NAME) printf("to""ken"#NAME"=%d\n", NAME)

a=1;PRINT(a); 得结果就就是tokena=1;

9.大小端得记忆口诀

小弟小,大弟大。即小端低位在小得地址,大端低位在大得地址。

一般x86使用小端,powerpc使用大端,ARM可以设置使用大端还就是小端

10.函数名得使用

函数名可以理解为就就是函数得入口地址(指针常量),在使用函数名时,如果只使用函数名进行赋值,后不带(),则会直接使用函数入口地址,例如:函数指针pfunc=func; 此时会把函数func得入口地址赋给函数指针pfunc

2.如果函数名后带(),则编译器知道就是调用函数,就会跳转到函数得入口地址。

test就是一个函数名,则test,&test与*test得值都就是函数得入口地址,*test可以这样理解,test就是函数得入口地址,*test就是取函数入口地址所指向得,也就就是函数名,=test,而函数名也就是函数得入口地址,所以*test得值也等于函数入口地址。

11.指针函数与函数指针

指针函数就是个函数(返回值就是一个指针得函数)函数指针就是个指针变量(只能指向函数得指针)

指针函数:int *a(int x,int y)就就是指针函数,()得优先级高于*,所以就是先a(int x,int y),表示函数,又因为返回值就是指针,所以就声明函数就是指针类型得,所以就在其前面加*。否则如果没有不加*得话,

int *ret;

int a(int x,int y);

ret = a(1,2);

最后一句ret = a(1,2);就会出错,因为等号左边就是个指针,而右边却就是个数值,编译会报错。

函数指针:强调就是个指针变量,所以变量名前得*要用()括起来(为了与指针函数区分),例如(*a),又因为就是只能指向函数得,所以指针变量后要跟与其对应得函数一样得参数列表,例如int (*a)(int x, int y),这表示它就是个指针变量(因为*a就是用()括起来得),就是个指向函数得指针变量。

函数指针只就是在声明得时候强制一定要使用(*a)(参数) 这种形式,在使用得时候(赋值与调用)可以随意,就是否使用*都可以,比如:

int (*a)(int x,int y); //声明

int test(int x,int y)

{……}

a=test; //使用,也可以*a=test, 或者a=&test,或者*a=&test,都一样得

a(1,2); //使用,也可以(*a)(1,2)

因为函数指针得作用就一个,就就是指向函数,所以不管怎么写,都就是要使用所指向得函数,没有歧义,所以为了使用者不至于不好理解应该怎么写,随便爱怎么写就怎么写。

另外:函数指针数组得写法就是int (*a[])(int, int) 可以对比定义指针数组int *a[] 12.用tepedef 定义函数指针得类型

使用方法就是:

定义: typedef void (*INTFUNC)(int)

声明:INTFUNC pfunc; 当成普通得定义变量一样

例如:

typedef void (*INTFUNC)(int)

void aaa(int x)

{……}

void main()

{

INTFUNC yyy;

yyy=aaa;

……

}

13.开头得数值会被视为八进制数

例如printf(“%d”,021); 结果打印17而非21,因为八进制得21就就是十进制得17

14.多维数组与指针

1.二维数组实际上就就是数组得数组,多维数组就就是数组得数组得数组……

2.二维数组定义:类型数组名[行总数][列总数]

例如int a[2][3]={{1,2,3},{4,5,6}};

a[m][n]可以理解为a得第一维元素个数就是m,第二维为n,即a中有m个元素,m个元素当中每个元素有n个元素,所以最后一个就就是最小维得,所以最里头得数组得长度要瞧最后一维得数字。

3.下标[]运算符:a[m]完全等价于*(a+m),a[m][n]完全等价于*(*(a+m)+n)

指向多维数组得指针定义,例如指向int a[50][100]得定义int (*p)[100]=a; 这样定义就是表示p就是一个指向具有长度100数组得指针(而不就是指针数组),类似地,三维数组可以这样定义:

int

a[2][3][4]={{{111,112,113,114},{121,122,123,124},{131,132,133,134}},{{211,212,213,214},{22 1,222,223,224},{231,232,233,234}}};

int (*p)[3][4]=a;

使用时,指针就相当于跟数组名完全等价了,完全可以像p[1][2][2]这样来使用,也可以用*(*(*(p+1)+2)+2)

注意!

1)、一定要用()括起来(*p),表明p就是个指针,而不就是指针数组(如果没有括号,就

变成了指针数组了)

2)、定义指针时,总比对应得数组少一维(少第一维),也就就是指针运算并不需要知道

第一维得长度。(可以这样理解记忆:指针算一维,所以指针那一维代替了第一维,因为像一维得时候int a[2]={1,2}; int *p=a; 相当于指针算作一维了。)

15.do while语句与while语句

do while语句得语法就是:do{语句}while(表达式);

while语句得语法就是:while(表达式){语句}

注意!do while语句后面有一个”;”而while语句没有

因为c语言在编译阶段会把所有得空格与回车都忽略掉,而如果do{语句}while(表达式)后面没有;得话,会引起误解,以为while就是跟下一句与在一起得,所以必须要;号来隔开,while(表达式)则不需要,因为有{},如果没有{}得话,也会就是一条语句,而语句后面就有;,所以不会因为误解,不需要;。

16.main函数参数

C语言规定可以带2个参数:

int main(int argc, char *argv[])

第一个参数就是int型,表示操作系统传递上来给main函数得参数个数,第二个就是个指针数组(字符串数组)

例如:

int main(int argc, char* argv[])

{

char **p=argv;

printf("argc=%d",argc);

do

{

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

*p++;

}

while(--argc>=1);

return 0;

}

这个函数编译出来为test3、exe,然后在dos命令行中调用,得到:

D:\>test3、exe aaa bbb ccc

argc=4argv=test3、exe

argv=aaa

argv=bbb

argv=ccc

其中,test3、exe文件名本身也算一个参数,所以dos命令行调用test3、exe时,操作系统传递给test3、exe得实参实际上就就是参数个数就是4,参数为

{“test3、exe”,“aaa”,”bbb”,”ccc”}

17.哪些语句句尾要用分号?

C语言规定,所有得语句必须要以分号;结尾,而预编译命令不属于语句,末尾不加分号,如#include #if #else #elif #endif #define等

18.volatile关键字得作用

volatile修饰得量就是不稳定得,可能会经常被改变或者被其她线程使用并改变其值,所以用volatile关键字就限制了执行器在执行得时候每次访问其值必须去内存中去取,而不能被编译器优化在内部寄存器中。

19.typedef得用法

1.用于对普通数据类型定义别名:例如,typedef unsigned int UINT;

用于定义指针:例如,typedef int *PINT; (注意!虽然*与PINT之间没有空格,但就是实际上跟typedef int* PINT就是一样得,*就是跟前面得结合得。)

3.用于对结构体/枚举/联合体类型定义别名:例如:

typedef union

{

int uid;

unsigned char mid;

} ID_U;

4.用来定义数组:例如,typedef int aNum[2]; aNum x;

5.用来定义函数相关,一般都就是定义函数指针:例如

typedef int (*pf)(int, char);

6.用来简化复杂得定义,其实就就是前面几个得综合。

注意!定义普通类型与指针以及结构体/联合体/枚举,都就是“typedef 原定义别名;”

得方式,而定义数组与函数指针就是按照“替换原定义得变量”得定义方式来定义,就是不同得。

typedef使用范例:

#include "stdafx、h"

#include "stdio、h"

typedef unsigned int UINT;

typedef struct

{

UINT uid;

char mid;

} STU_T;

typedef STU_T *STU_T_REF;

typedef int aArray[2];

typedef void (*fFunc)(int);

void print1(int x)

{

printf("%d",x);

}

int main(int argc, char* argv[])

{

UINT i=3;

STU_T st1;

STU_T_REF tStu;

aArray b;

fFunc fTestPrint;

tStu = &st1;

tStu->uid = i;

b[0]=1;

b[1]=2;

fTestPrint = &print1;

fTestPrint(tStu->uid);

return 0;

}

20.typedef 与define区别

1.作用上,typedef就是定义一个类型,使用时与普通得变量类型用法完全相同;define就

是宏替换

2.语法上,typedef: typedef char INT8;

define: #define INT8 char

●typedef 在执行时执行←------→ #define 在预编译时执行

typedef 就是一条语句,后要分号←------→#define 就是预编译指令,后无需分

typedef 别名/替换者在后,原名在前←------→ #define 别名/替换者在前,原名在后

(这点可以这样记忆:执行前,使用前;执行后,使用后。#define就是预编译,typedef

就是语句,所以#define得执行就是前,我们使用得那个也在前,即#define INT8

char ,INT8在前,原名在后;typedef得执行就是后,我们使用得那个也在后,即

typedef char INT8; 我们使用得INT8也在后)

typedef只能用于类型定义←----→#define 不受限制,除了类型外还可以就是数值

typedef不能带参数←----→#define 可以带参数

3.作用范围上,语句

typedef (int *) PINT; PINT a,b;

与#define PINT (int *)

PINT a,b;

中得PINT a,b;就是不一样得,前者相当于int *a;int *b; 而后者相当于int *a,b;即int *a; int b;

21.复杂定义得剖解方法与用typedef简化

可以用“右左法则”来分析,所谓右左法则,就就是先找到没有定义得变量,这个就就是分析得起点,也就是变量得最终属性,从这个起点,根据优先级顺序开始分析,如优先级相同,则按照先右再左分析,遇到()就根据()就是最高优先级来分析,跳出()后同样按先右后左分析,以此类推。例如:

int* (*a[5])(int, char*);找到a就是未定义变量,所以这就就是起点,[]优先级比*高,所以a与[5]先结合,a[5]就是一个具有5个元素得数组,再与*结合,得到每个元素都就是指针,跳出()再向右结合(),得到前面得指针(数组里得每个都就是指针得元素)指向一个函数,函数

得参数就是(int, char *),返回值就是int *。

void (*b[10]) (void (*)()); b就是一个有10个元素得数组,每个元素都就是指针,这些指针中每一个指针指向一个函数,函数得参数就是void(*)()(实际上它又就是个函数指针,指针所指向得函数得参数为空,返回值为void),返回值就是void

double(*)()(*pa)[9]; pa就是一个指针,这个指针指向具有9个元素得数组,9个元素中每一个都就是double(*)(),即指针,指针指向一个函数,函数得参数为空,返回值为double。

使用typedef简化:

用typedef来对复杂定义做简化很简单,从小到大,抠出合适得定义单位(从阅读理解与使用上合适),然后用别名代替,最后在前面加个typedef关键字即可。

例如:

1).int* (*a[5])(int, char*); ---首先从小到大,抠出合适得定义单位,a[5]就是个数组,方便理解,别名用ARRAY替代,则成了int* (*ARRAY)(int, char*);前加一个typedef即可,

typedef int *(*ARRAY)(int,char*)

2)、void (*b[10])(void (*)());

typedef void (*pfA)(void (*)()); pfA b[10]; 进一步化简->

typedef void (*pfB)(); typedef void (*pfA)(pfB); pfA b[10];

3)、double(*(*pa)[9])();

typedef double(*PF)(); PF (*pa)[9];

22.struct enum与union得定义以及用typedef来定义

定义:

struct/enum/union 类型名{成员类型成员名; 成员类型成员名; ……};

(其中如果直接在}后定义变量得话,可以省略类型名不写)

声明:

struct/enum/union类型名变量名;

例如:

定义:struct student_s{char * name; int age; int class; int number;};

声明:struct student_s stu_a;

用typedef来定义:

typedef struct/enum/union 类型名{成员类型成员名;……} 别名;

(其中可以省略类型名)

声明:别名变量名;

例如:

定义:typedef struct student_td{char *name; int age; int class; int number;} STUDENT_T;

使用:STUDENT_T stu_a;

用typedef来定义结构体/枚举/联合体实际上就就是:typedef 原定义别名; 与定义普通

得类型就是一样得,如typedef char INT8;

23.typedef得2个使用陷阱

1.用在const或volatile修饰得语句时得陷阱

typedef用在const修饰得语句与用在volatile修饰得语句得注意点就是一样得,下面以const 为例说明。

typedef int *PINT;

const PINT p1;

上面2条语句,先用typedef声明了之后,再用const修饰,实际结果不就是const int * p1; 而就是int * const p1; 根我们想象得不一样得!不能直接类似#define那样替换得!

因为typedef定义得PINT就是地址,所以const修饰得就是地址,也就就是p1不能被修改,而不就是整个(int *p1)!二维得也类似,typedef int **PPINT; int i=2; int *p=&i; PPINT p1=&p; 就是p1不能被修改,而不就是(**p1)!

2.typedef不能跟存储类关键字同时使用

typedef在语法上属于存储类关键字(如auto, static, extern, mutable,register等),不能再跟另外得存储类关键字同时使用了,虽然它并不实际影响存储特性。

如:不能typedef static int SINT; 编译会提示“more than one storage class specified使用了一个以上得存储类关键字”

24.为什么要使用extern “C”

extern “C”就是用来修饰extern声明得,使extern按照C得形式去声明,而不就是C++得形式,就是为了兼容C与C++混合编程时防止c++程序调用c程序时找不到对应函数而设置得。

详细解释: c++为了实现面相对象而引入函数重载(重载就就是允许同样得函数名而参数不同,因为面相对象就要求能进行函数重载,因为面相对象就是把一个行为(即方法/函数)对应得各种情况(即不同类型得参数,比如说println函数就是打印,但就是有时可能传递得参数只就是字符串,有时候既有数字,又有字符串,不止一个,可能各种使用情况参数类型与个数都不同)都封装在对象内部,而不直接对外呈现),通过改变函数得编译方法来实现,实际上就就是编译时用函数构建符号表得时候生成得对应得函数名不同,比如同样得函数foo(int,int),c语言编译在符号表中就是__foo,而c++编译在符号表中却就是__foo_int_int)。正就是由于这点,所以、cpp代码在调用函数时总就是寻找按照c++编译得符号表得形式来寻找函数名,而、c文件编译出来得放在符号表得函数名却不就是c++所想象那样得,所以、cpp文件在调用c文件函数时就找不到函数了。所以需要使用extern “C”来修饰extern,意思就是告诉C++编译器,这句extern要按照c得方式去寻找函数。具体得结合实例得解析与extern “C”得使用方法如下:

以以下例子说明:

/*----------test6、cpp--------------*/

extern int add(int x,int y);

int main(int argc, char* argv[])

{

add(2,3);

return 0;

}

/*----------cExample、c--------------*/

int add( int x, int y )

{

return x + y;

}

过程分析:

在编译test6、cpp文件得时候,因为就是cpp文件,在编译得时候就会按照c++得方式去编译,也就就是在寻找add函数得时候根据extern int add(int x,int y);语句实际上就是寻找__add_int_int符号表得,因为有这个extern语句,所以编译可以通过;

在编译cExample、c得时候,因为就是、c文件,所以按照c得方式去编译,得到add 函数对应在符号表上函数名就是__add,当然因为没有语法错误编译也能通过。

链接得时候,链接到、cpp生成得编译文件(linux下就是、o)得调用add函数语句时,会去其她文件得符号表去找__add_int_int函数,实际上编程者得本意就是函数在cExample、c中定义得add函数,但就是在cExample、c对应得编译文件(linux下就是cExample、o)得符号表中没有找到__add_int_int符号(因为add函数被用c得方式编译成了__add了),在其她文件中也没有找到,所以就会报这个符号无法解析得错误。

解决方法:在cpp文件中得extern函数得时候使用extern “C”,可以有2种书写方式:

1、用extern “C”代替extern语句。改成extern “C” int add(int x,int y);即可

2、用extern “C”{}将所有得extern语句括起来。

extern “C”

{

extern int add(int x,int y);

}

这样做得好处就就是可以一次性得把所有得extern语句都用extern “C”限制了,{}中间还可以有其她得语句,例如#define, typedef等,对它们没有影响。

注意!使用这种方法要注意extern “C”只有c++编译器能识别出来,而c编译器不能识别,所以一定不能把extern “C”放在c编译器所编译到得地方,因为、c文件就是c编译器编译得,所以不要把extern “C”放在c文件中。但就是常常在项目中我们会将extern声明放在、c文件对应得、h中,而、c文件常常会包含、h文件(当然、h文件也可能会被其她得、cpp文件包含),所以我们常常利用__cplusplus宏来隔开,可以这样:

/*----------cExample、h--------------*/

#ifndef __CEXAMPLE_H

#define __CEXAMPLE_H

#ifdef __cplusplus

extern “C”{

#endif

extern int add(int,int);

c语言if语句练习题

c语言if语句练习题 1、输入一个学生成绩,判断并输出该学生是否及格。 #include main { int a; printf ; scanf ; if printf ; else switch { case 0: case 1: case: case: case: case: printf ; break; 为B\n”); } }

2、输入三角形的三条边长,求三角形的周长和面积,若不能构成三角形,输出提示。拓展练习:根据用户输入的三角形的三条边长判定是何种三角形。 提示:正三角形——三边相等; 等腰三角形——三边中有两边相等; 直角三角形——两边的平房和等于第三边平方。 case: printf; break; case: printf; break; case: printf; #include #include main { float a,b,c,d; \n”); printf ; d=/2; if { if {printf ; printf ; } else { if { printf ; printf **),a+b+c); } else { if

{ printf ; printf **),a+b+c); } else { printf ; printf **),a+b+c); } } } } else printf ; } 3、输入3个分别表示箱子长、宽、高的整数值,判断并输出该箱子是正方体还是长方体。 ? 马克思手稿中有一道趣味数学题:有30个人,其中有男人、女人和小孩,在一家饭馆里吃饭 共花了50先令,每个男人各花3先令,每个女人各花2先令,每个小孩各花1先令,问男人、女人和小孩各有几人?

c语言if的用法

c语言if的用法 条件condition可以是任何返回布尔值的表达式。 else子句是可选的。 if语句的执行过程如下:如果条件为真,就执行if的对象(statement1);否则,执行else的对象(statement2)。 任何时候两条语句都不可能同时执行。 考虑下面的例子:int a,b;if(a 任何情况下都不可能使a和b 都被赋值为0。 记住,直接跟在if 或else语句后的语句只能有一句。 如果你想包含更多的语句,你需要建一个程序块,如下面的例子:int bytesAvailable;if (bytesAvailable > 0) {ProcessData();bytesAvailable -= n;} elsewaitForMoreData();这里,如果变量bytesAvailable 大于0,则if 块内的所有语句都会执行。 嵌套if 语句嵌套(nested)if语句是指该if语句为另一个if或者else语句的对象。 在编程时经常要用到嵌套if语句。 当你使用嵌套if语句时,需记住的要点就是:一个else语句总是对应着和它同一个块中的最近的if语句,而且该if语句没有与其他else 语句相关联。 下面是一个例子:if(i == 10) {if(j 100) c = d; // this if iselse a = c; // associated with this else}else a = d; // this else refers to if(i ==

10)如注释所示,最后一个else语句没有与if(j 最后一个else语句对应着if(i==10)。 内部的else语句对应着if(k>100),因为它是同一个块中最近的if 语句。 if-else-if 阶梯基于嵌套if语句的通用编程结构被称为if-else-if 阶梯。 它的语法如下:if(condition)statement;else if(condition)statement;else if(condition)statement;elsestatement;条件表达式从上到下被求值。 一旦找到为真的条件,就执行与它关联的语句,该阶梯的其他部分就被忽略了。 如果所有的条件都不为真,则执行最后的else语句。 最后的else语句经常被作为默认的条件,即如果所有其他条件测试失败,就执行最后的else语句。 如果没有最后的else语句,而且所有其他的条件都失败,那程序就不做任何动作。 . 下面的程序通过使用if-else-if阶梯来确定某个月是什么季节。 // Demonstrate if-else-if statements.main() {int month = 4; // Aprilif (month == 12 || month == 1 || month == 2)printf ( "Winter");else if (month == 3 || month == 4 || month == 5)printf ("Spring");else if (month == 6 || month == 7 || month == 8)printf ( "Summer");else if (month == 9

c语言if语句的练习题答案

c语言i f语句的练习题答 案 Prepared on 24 November 2020

1、编写程序输入a和b,求a和b的余数和商。 #include<> voidmain() { inta,b; scanf("%d%d",&a,&b); printf("商为%d余数为%d",a/b,a%b); } 2、输入一个整型数据,分别求出各位数字。如:469,则个位数是9,十位数 是6,百位数是4。 #include<> voidmain() {inta,m=0; intt,t1,t2,t3,t4; scanf("%d",&a); if(a<0||a>99999) printf("输入数据超出范围\n"); elseif(a>=0&&a<10) {m=1; printf("该数是%d位数,其个位数为%d\n",m,a); } elseif(a>=10&&a<100) { m=2; t=a%10; a=a/10; printf("该数是%d位数,其个位数为%d十位数为%d\n",m,t,a); } elseif(a>=100&&a<1000) { m=3; t=a%10; t1=(a/10)%10; t2=a/100; printf("该数是%d位数,其个位数为%d十位数为%d百位数为%d\n",m,t,t1,t2);

elseif(a>=1000&&a<10000) { m=4; t=a%10; t1=a/10%10; t2=a/100%10; t3=a/1000; printf("该数是%d位数,其个位数为%d十位数为%d百位数为%d千位数字 为%d\n",m,t,t1,t2,t3); } elseif(a>=10000&&a<100000) { m=5; t=a%10; t1=a/10%10; t2=a/100%10; t3=a/1000%10; t4=a/10000; printf("该数是%d位数,其个位数为%d十位数为%d百位数为%d千位数字为%d 万位数字为%d\n",m,t,t1,t2,t3,t4); } } 以上写法太繁琐了,如果学习了循环,则简单很多。 #include<> voidmain() { inta,b; intn=0; scanf("%d",&a); while(a)//while(a!=0) {n++;//n用来统计数字a是几位数,n的初值必须为0 b=a%10; a=a/10;//a/=10; printf("%d",b);//输出a的各位数字 } printf("a的位数为%d",n);//此语句必须写在循环体的外面

C语言中# ifdef和# elseif的使用技巧和注意事项

下面这几个宏是为了进行条件编译。一般情况下源程序中所有的行都参加编译。但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一部分内容指定编译的条件,这就是“条件编译”。有时,希望当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。 条件编译命令最常见的形式为: #ifdef 标识符 程序段1 #else 程序段2 #endif 它的作用是:当标识符已经被定义过(一般是用#define命令定义),则对程序段1进行编译,否则编译程序段2。 其中#else部分也可以没有,即: #ifdef 程序段1 #denif 这里的“程序段”可以是语句组,也可以是命令行。这种条件编译可以提高C源程序的通用性。如果一个C源程序在不同计算机系统上运行,而不同的计算机又有一定的差异。例如,我们有一个数据类型,在Windows平台中,应该使用long类型表示,而在其他平台应该使用float表示,这样往往需要对源程序作必要的修改,这就降低了程序的通用性。可以用以下的条件编译: #ifdef WINDOWS #define MYTYPE long #else #define MYTYPE float #endif 如果在Windows上编译程序,则可以在程序的开始加上 #define WINDOWS 这样则编译下面的命令行: #define MYTYPE long 如果在这组条件编译命令之前曾出现以下命令行: #define WINDOWS 0 则预编译后程序中的MYTYPE都用float代替。这样,源程序可以不必作任何修改就可以用于不同类型的计算机系统。当然以上介绍的只是一种简单的情况,可以根据此思路设计出其它的条件编译。 例如,在调试程序时,常常希望输出一些所需的信息,而在调试完成后不再输出这些信息。可以在源程序中插入以下的条件编译段:

C语言中if和goto的用法

C语言中,if是一个条件语句,用法 if(条件表达式) 语句 如果满足括号里面表达式,表示逻辑为真于是执行后面的语句,否则不执行(表达式为真则此表达式的值不为0,为假则为0,也就是说,如果括号里面不是一个判断表达式,你填了一个不是0的数字或其他,表示条件永远为真,一定执行后面的语句,反之,你填了一个0,则永远不会执行后面的语句)。 if后面的语句如果多于一句,可以放在{}里面作为复合语句, 例: int a=2,b=1; if(a>b) cout<<"a>b"<1 ,表达式a>b为真,于是执行后面的语句,输出a>b 这几个字符。 goto 是转向语句,按其英文含义就可理解 用法标号:语句; ...................... goto 标号; 或者 goto 标号; ..................... 标号:语句; 标号和goto必须包括处于同一个函数内标号的写法跟变量名一样不能和关键词相同,后面必须带冒号 当程序执行到goto这个语句时,程序就转跳到标号后面的语句去了 例 int x=1; biaohao: x=x+1; if(x<100) goto biaohao; cout<<"x=100"<

C中goto语句的用法 个人觉得goto用在内层循环中比较合适,用break只能跳出内层循环,而goto可以直接跳出最外层循环,在合理的地方使用就可以了。debian:/home/server# vi goto.c #include #include int main() { int i, j; for (j = 0; j < 3; j++) { for (i = 0; i < 10; i++) { printf("j: %d, i: %d\n", j, i); if (i == 3) goto last; } } last: printf("This is the last line\n"); return 0; } debian:/home/server# gcc -o goto goto.c

C语言if语句总结

C语言选择语句 C语言支持两种选择语句:if语句和switch语句。这些语句允许你只有在程序运行时才能。知道其状态的情况下,控制程序的执行过程。首先看一下if语句的用法: if语句: if语句是c语言中的条件分支语句。它能将程序的执行路径分为两条。if语句的完整格式如下: if (condition) statement1;; else statement2; 其中,if和else的对象都是单个语句(statement),也可以是程序块。条件condition可以是任何返回布尔值的表达式。else子句是可选的。 if语句的执行过程如下:如果条件为真,就执行if的对象(statement1);否则,执行else的对象(statement2)。任何时候两条语句都不可能同时执行。考虑下面的例子: int a,b; if(a < b) a = 0; else b = 0; 本例中,如果a小于b,那么a被赋值为0;否则,b被赋值为0。任何情况下都不可能使a 和b都被赋值为0。 记住,直接跟在if 或else语句后的语句只能有一句。如果你想包

含更多的语句,你需 要建一个程序块,如下面的例子: int bytesAvailable; if (bytesAvailable > 0) { ProcessData(); bytesAvailable -= n; } else waitForMoreData(); 这里,如果变量bytesAvailable 大于0,则if块内的所有语句都会执行。 嵌套if 语句 嵌套(nested)if语句是指该if语句为另一个if或者else语句的对象。在编程时经常要用到嵌套if语句。当你使用嵌套if语句时,需记住的要点就是:一个else语句总是对应着和它同一个块中的最近的if语句,而且该if语句没有与其他else语句相关联。下面是一个例子:if(i == 10) { if(j < 20) a = b; if(k > 100) c = d; // this if is else a = c; // associated with this else } else a = d; // this else refers to if(i == 10) 如注释所示,最后一个else语句没有与if(j <20)相对应,因为它

c语言中if语句知识点总结

If语句知识点总结 一. if语句的三种基本形式 (1)if (表达式)语句; 例:if(x>y) printf(“%d”,x); (2)if(表达式) 语句1; else语句2; 例:if (x>y) printf(“%d”,x); else printf(“%d”,y); (3)if(表达式1)语句1; else if(表达式2)语句2; else if(表达式3)语句3; ……

else if(表达式m)语句m; else 语句n; 例:if (number>10)cost=0.15; else if(number>30)cost=0.10; else if(number>100)cost=0.075; else if(number>500)cost=0.05; else cost=0.01; c语言中的六大陷阱 1.if(表达式)一般为逻辑表达式或关系表达式输出1/0,但原则上可以是任何变量、常量和表达式; 2.if(常量)--C语言中任何非零的数都被认作为真; 例一:int i=5; if(2)printf("%d\n",++i); else printf("%d\n",--i); 输出值:6 例二:int i=5,a=3,b; if(b=a)printf("%d\n",++i); /*上面括号里“b=a”即将a的值赋给b,所以该条件为真*/

else printf("%d\n",--i); 输出值:6 例三:int i=5,a=3,b=9; if(b==a)printf("%d\n",++i); /*括号中“==”含义为“等于”,所以是假*/ else printf("%d\n",--i); 输出值:4 3.注意:if(表达式)语句;表达式里面是"=="还是"=" 4.如果if后面的表达式是多个关系表达式,要注意关系运算符 是两两进行比较的!!!!!!! int a=6,b=5,c=4,i=5; if(a>b>c)printf("%d\n",++i); /*括号中“a>b>c”,先判断“a>b”,为真,值为1;然后判断“1>c”,为假,所以“a>b>c”为假*/ else printf("%d\n",--i); 输出值:4 5.复合语句:>=2条的语句用{}括起来,共同完成一定功能 注意复合语句的用法! 6.在上机改错题中,如果在if语句后面的表达式中出现“=”,90%要将“=”改为“==”。 可乐雪碧原理/*输入两个实数,由小到大输出*/ 超级考点:交换 e.g. #include void main( ) {

c语言if语句的练习题答案

1、编写程序输入 a 和 b ,求 a 和 b 的余数和商。 #include<> voidmain() { inta,b; scanf("%d%d",&a,&b); printf("商为%d 余数为%d",a/b,a%b); } 2、输入一个整型数据,分别求出各位数字。如:469,则个位数是 9,十位数是 6, 百位数是 4。 #include<> voidmain() {inta,m=0; intt,t1,t2,t3,t4; scanf("%d",&a); if(a<0||a>99999) printf(" 输入数据超出范围 \n"); elseif(a>=0&&a<10) {m=1; printf(" 该数是 %d 位数,其个位数为 %d\n",m,a); } elseif(a>=10&&a<100) { m=2; t=a%10; a=a/10; printf("该数是%d位数,其个位数为%d十位数为%d\n",m,t,a); } elseif(a>=100&&a<1000) { m=3; t=a%10; t1=(a/10)%10; t2=a/100; printf("该数是%d位数,其个位数为 %d十位数为%d百位数为%d\n",m,t,t1,t2); } elseif(a>=1000&&a<10000) { m=4; t=a%10; t1=a/10%10; t2=a/100%10; t3=a/1000; printf("该数是%d位数,其个位数为%d十位数为%d百位数为%d千位数字 为%d\n",m,t,t1,t2,t3); } elseif(a>=10000&&a<100000) { m=5; t=a%10; t1=a/10%10; t2=a/100%10; t3=a/1000%10; t4=a/10000; printf(" 该数是 %d 位数,其个位数为 %d 十位数为 %d 百位数为 %d 千位数字为 %d 万位数字为%d\n",m,t,t1,t2,t3,t4); } } 以上写法太繁琐了,如果学习了循环,则简单很多。 #include<>

c语言(if语句)练习题

If 语句练习 一、程序填空: 输入3个数分别是a 、b 、c 。先将a 、b 中的较大致存入a 中、较小数存入b 中;再让a 与c 比较,将a 与c 中的较大数存在a 中,较小数存人c 中;最后比较b 与c ,将b 、c 中的较大数存入b 中,较小数存入c 中。这样a 、b 、c 这3个数的序列即按从大到小排列。 #include main() { int a,b,c,t; printf(“Input three integers:”); scanf(“%d,%d,%d ”, ); /*输入a ,b ,c3个整数*/ if(a?=?--≤?? 分析下列程序代码能否实现,如果程序中存在错误,请修改程序中的错误,然后运行修改后的程序。 #include main() { int x,y; scanf(“%d ”,&x); if(x*x – 10>0); y = x*x; printf(“y= %d\n ”,y); else y=-(x*x); printf(“y=%d\n ”,y); } 三、编程题 1、编写程序从键盘上输入两个整数,检查第一个数是否能被第二个数整除。

2、编写一个程序,输入某人的身高(cm)和体重(kg),按下式确定其体重是否为标准、过胖或过瘦。(1)标准体重=身高-110;(2)超过标准体重5kg(即大于5kg)为过胖;(3)低于标准体重5kg(即小于5kg)为过瘦。 3、判断某一年是否是闰年: (1) 被4整除但不能被100整除; 或(2) 被400整除; 4、编写程序计算升高:每个做父母的都关心自己孩子成人后的身高,据有关生理卫生知识与数理统计分析表明,影响小孩成人后身高的因素有遗传、饮食习惯与坚持体育锻炼等。小孩成人后身高与其父母身高和自身性别密切相关。设faHeight为其父身高,moHeight为其母身高,身高预测公式为: 男性成人时身高= (faHeight + moHeight) * 0.54(cm) 女性成人时身高= (faHeight * 0.923 + moHeight) / 2(cm) 此外,如果喜爱体育锻炼,那么可增加身高2%,如果有良好的卫生饮食习惯,那么可增加身高1.5%。 程序要求:父亲的身高与母亲的身高、小孩的性别、是否喜爱体育锻炼和是否有良好的卫生饮食习惯也从键盘上输入,最终输出预测的身高。 提示:小孩性别的输入方式,可在屏幕给出提示“请输入小孩的性别(男孩输入M,女孩输入F):”,然后通过if语句来判断从键盘输入的字符是M还是F。是否喜爱体育锻炼也可以通过类似的方式实现。 演示效果如下:

c语言中if语句知识点总结(可编辑修改word版)

If语句知识点总结 一.if语句的三种基本形式 (1)if (表达式)语句; 假 例: if(x>y) printf(“%d”,x); (2)if(表达式) 语句1; else语句2; 例:if (x>y) printf(“%d”,x); else printf(“%d”,y); (3)if(表达式1)语句1; else if(表达式2)语句2; else if(表达式3)语句3; ……

else if(表达式m)语句m; else 语句n; 例:if (number>10)cost=0.15; else if(number>30)cost=0.10; else if(number>100)cost=0.075; else if(number>500)cost=0.05; else cost=0.01; c语言中的六大陷阱 1.if(表达式)一般为逻辑表达式或关系表达式输出1/0,但原则上可以 是任何变量、常量和表达式; 2.if(常量)--C语言中任何非零的数都被认作为真; 例一:int i=5; if(2)printf("%d\n",++i); else printf("%d\n",--i); 输出值:6 例二:int i=5,a=3,b; if(b=a)printf("%d\n",++i); /*上面括号里“b=a”即将a的值赋给b,所以该条件为真*/

else printf("%d\n",--i); 输出值:6 例三:int i=5,a=3,b=9; if(b==a)printf("%d\n",++i); /*括号中“==”含义为“等于”,所以是假*/ else printf("%d\n",--i); 输出值:4 3.注意:if(表达式)语句;表达式里面是"=="还是"=" 4.如果if后面的表达式是多个关系表达式,要注意关系运算符 是两两进行比较的!!!!!!! int a=6,b=5,c=4,i=5; if(a>b>c)printf("%d\n",++i); /*括号中“a>b>c”,先判断“a>b”,为真,值为1;然后判断“1>c”,为假,所以“a>b>c”为假*/ else printf("%d\n",--i); 输出值:4 5.复合语句:>=2条的语句用{}括起来,共同完成一定功能 注意复合语句的用法! 6.在上机改错题中,如果在if语句后面的表达式中出现“=”,90%要将 “=”改为“==”。 可乐雪碧原理/*输入两个实数,由小到大输出*/ 超级考点:交换 e.g. #include void main( ) {

c语言if语句的练习题答案

1、编写程序输入a和b,求a和b的余数和商。 #include<> void main() { int a,b; scanf("%d%d",&a,&b); printf("商为%d 余数为%d",a/b,a%b); } 2、输入一个整型数据,分别求出各位数字。如:469,则个位数是9,十位数是6,百位数 是4。 #include<> void main() { int a,m=0; int t,t1,t2,t3,t4; scanf("%d",&a); if(a<0||a>99999) printf("输入数据超出范围\n"); else if (a>=0&&a<10) { m=1; printf("该数是%d位数,其个位数为%d\n",m,a); } else if(a>=10&&a<100) { m=2; t=a%10; a=a/10; printf("该数是%d位数,其个位数为%d 十位数为%d\n",m,t,a); } else if(a>=100&&a<1000) { m=3; t=a%10; t1=(a/10)%10; t2=a/100; printf("该数是%d位数,其个位数为%d 十位数为%d 百位数为%d\n",m,t,t1,t2); } else if(a>=1000&&a<10000) { m=4; t=a%10; t1=a/10%10; t2=a/100%10; t3=a/1000; printf("该数是%d位数,其个位数为%d 十位数为%d 百位数为%d 千位数字

为%d\n",m,t,t1,t2,t3); } else if(a>=10000&&a<100000) { m=5; t=a%10; t1=a/10%10; t2=a/100%10; t3=a/1000%10; t4=a/10000; printf("该数是%d位数,其个位数为%d 十位数为%d 百位数为%d 千位数字为%d 万位数字为%d\n",m,t,t1,t2,t3,t4); } } 以上写法太繁琐了,如果学习了循环,则简单很多。 #include<> void main() { int a,b; int n=0; scanf("%d",&a); while(a)//while(a!=0) { n++;//n用来统计数字a是几位数,n的初值必须为0 b=a%10; a=a/10;//a/=10; printf("%d",b);//输出a的各位数字 } printf("a的位数为%d",n);//此语句必须写在循环体的外面 } 3、编程输入两个整型数据a和b,若a2+b2的结果大于100,则输出a2+b2的值,否则输出 a+b的结果。 #include<> void main() { int a,b; scanf("%d%d",&a,&b); if(a*a+b*b>100) printf("%d\n",a*a+b*b); else printf("%d\n",a+b); } //还可以用一个变量来表示a2+b2的值 4、输入两个整数a和b,若a3-b3小于0,则输出a-b的值,否则输出a3-b3的结果。 #include<> void main()

C语言if语句详解

C语言if语句详解 用if语句可以构成分支结构。它根据给定的条件进行判断,以决定执行某个分支程序段。C 语言的if语句有三种基本形式。 语句的三种形式 1)第一种形式为基本形式:if if(表达式) 语句 其语义是:如果表达式的值为真,则执行其后的语句,否则不执行该语句。其过程可表示为下图。

本例程序中,输入两个数a、b。把a先赋予变量max,再用if语句判别max和b的大小,如max小于b,则把b赋予max。因此max中总是大数,最后输出max的值。 2) 第二种形式为: if-else if(表达式) 语句1; else 语句2; 其语义是:如果表达式的值为真,则执行语句1,否则执行语句2 。其执行过程可表示为下图。

输入两个整数,输出其中的大数。改用if-else语句判别a,b的大小,若a大,则输出a,否则输出b。 3) 第三种形式为if-else-if形式 前二种形式的if语句一般都用于两个分支的情况。当有多个分支选择时,可采用if-else-if 语句,其一般形式为: if(表达式1) 语句1; else if(表达式2) 语句2; else if(表达式3) 语句3; … else if(表达式m) 语句m; else 语句n; 其语义是:依次判断表达式的值,当出现某个值为真时,则执行其对应的语句。然后跳到整个if语句之外继续执行程序。如果所有的表达式均为假,则执行语句n。然后继续执行后

续程序。if-else-if语句的执行过程如下图所示。

本例要求判别键盘输入字符的类别。可以根据输入字符的ASCII码来判别类型。由ASCII 码表可知ASCII值小于32的为控制字符。在“0”和“9”之间的为数字,在“A”和“Z”之间为大写字母,在“a”和“z”之间为小写字母,其余则为其它字符。这是一个多分支选择的问题,用if-else-if语句编程,判断输入字符ASCII码所在的范围,分别给出不同的输出。例如输入为“g”,输出显示它为小写字符。 在使用if语句中还应注意以下问题: ?本语句的语义是,把b值赋予a,如为非0则输出该值,否则输出“a=0”字符串。这种用法在程序中是经常出现的。 ?在if语句中,条件判断表达式必须用括号括起来,在语句之后必须加分号。 ?在if语句的三种形式中,所有的语句应为单个语句,如果要想在满足条件时执行一组(多个)语句,则必须把这一组语句用{}括起来组成一个复合语句。但要注意的是在}之后不能再加分号。例如:

c语言中多个if的用法

c语言中多个if的用法 c语言中多个if的用法的用法如下:用if语句可以构成分支结构。 它根据给定的条件进行判断,以决定执行某个分支程序段。 C语言的if语句有三种基本形式。 语句的三种形式1) 第一种形式为基本形式:ifif(表达式) 语句其语义是:如果表达式的值为真,则执行其后的语句,否则不执行该语句。 其过程可表示为下图。 【例5-3】01.#include 02.int main(void){03. int a,b,max;04. printf("\n input two numbers: ");05. scanf("%d%d",&a,&b);06. max=a;07. if (max把a先赋予变量max,再用if语句判别max和b的大小,如max小于b,则把b赋予max。 因此max中总是大数,最后输出max的值。 2) 第二种形式为: if-elseif(表达式)语句1;else语句2;其语义是:如果表达式的值为真,则执行语句1,否则执行语句2 。 其执行过程可表示为下图。 【例5-4】01.#include 02.int main(void){03. int a, b;04. printf("input two numbers: ");05. scanf("%d%d",&a,&b);06. if(a>b)07. printf("max=%d\n",a); 改用if-else语句判别a,b的大小,若a大,则输出a,否则输出b。 3) 第三种形式为if-else-if形式前二种形式的if语句一般都用于两个分支的情况。

当有多个分支选择时,可采用if-else-if语句,其一般形式为:if(表达式1)语句1;else if(表达式2)语句2;else if(表达式3)语句3;…else if(表达式m)语句m;else语句n;其语义是:依次判断表达式的值,当出现某个值为真时,则执行其对应的语句。 然后跳到整个if语句之外继续执行程序。 如果所有的表达式均为假,则执行语句n。 然后继续执行后续程序。 if-else-if语句的执行过程如下图所示。 【例5-5】01.#include 02.int main(void){03. char c;04. printf("input a character: ");05. c=getchar();06. if(c='0'&&c='A'&&c='a'&&c这是一个多分支选择的问题,用if-else-if语句编程,判断输入字符ASCII 码所在的范围,分别给出不同的输出。 例如输入为“g,输出显示它为小写字符。 在使用if语句中还应注意以下问题: 1. 在三种形式的if语句中,在if关键字之后均为表达式。 该表达式通常是逻辑表达式或关系表达式,但也可以是其它表达式,如赋值表达式等,甚至也可以是一个变量。 例如:if(a=5) 语句;if(b) 语句;都是允许的。 只要表达式的值为非0,即为“真。 如在:if(a=5)…;中表达式的值永远为非0,所以其后的语句总是要执行的,当然这种情况在程序中不一定会出现,但在语法上是合法的。

相关主题
文本预览
相关文档 最新文档