关键字:while、typedef

运算符:=、-、*、/、%、++、--、(类型名)

C语言的各种运算符,包括用于普通数学运算的运算符

运算符优先级以及语句、表达式的含义

while循环

复合语句、自动类型转换和强制类型转换

如何编写带有参数的函数

目录

5.1 循环简介

5.2 基本运算符(operator)

5.2.1 赋值运算符:=

5.2.2 加法运算符:+

5.2.3 减法运算符:-

5.2.4 符号运算符:-和+

5.2.5 乘法运算符:*

5.2.6 除法运算符:/

5.2.7 运算符优先级

5.2.8 优先级和求值顺序

5.3 其他运算符

5.3.1 sizeof运算符和size_t类型

5.3.2 求模运算符:%

5.3.3 递增运算符:++

5.3.4 递减运算符:--

5.3.5 优先级

5.3.6 不要自作聪明

5.4 表达式和语句

5.4.1 表达式

5.4.2 语句

5.4.3 复合语句(块)

5.5 类型转换

5.6 带参数的函数

5.7 示例程序

5.8 关键概念

5.9 小结


5.1 循环简介

/* shoes2.c -- calculates foot lengths for several sizes */
#include <stdio.h>
#define ADJUST 7.31              // one kind of symbolic constant
int main(void)
{const double SCALE = 0.333;  // another kind of symbolic constantdouble shoe, foot;printf("Shoe size (men's)    foot length\n");shoe = 3.0;while (shoe < 18.5)      /* starting the while loop */{                        /* start of block          */foot = SCALE * shoe + ADJUST;printf("%10.1f %15.2f inches\n", shoe, foot);shoe = shoe + 1.0;}                        /* end of block            */printf("If the shoe fits, wear it.\n");return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ clang shoes2.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
Shoe size (men's)    foot length3.0            8.31 inches4.0            8.64 inches5.0            8.97 inches6.0            9.31 inches7.0            9.64 inches8.0            9.97 inches9.0           10.31 inches10.0           10.64 inches11.0           10.97 inches12.0           11.31 inches13.0           11.64 inches14.0           11.97 inches15.0           12.30 inches16.0           12.64 inches17.0           12.97 inches18.0           13.30 inches
If the shoe fits, wear it.

5.2 基本运算符(operator)

5.2.1 赋值运算符:=

术语:数据对象、左值、右值。

赋值表达式语句的目的是把值存储到内存位置上,用于存储值的数据存储区域统称为数据对象(data object),C标准只有这个地方是提到对象这个术语。使用变量名是标识对象的一种方法,除此之外,还有指定数组的元素、结构的成员、指针表达式(所指对象的地址)等等。

左值(lvalue)是用于标识或定位特定数据对象存储位置的标签,可修改的左值(modifiable lvalue),用于标识可修改的对象 = 对象定位值(object locator value)。

右值(rvalue)是能赋值给可修改左值的量,且本身不是左值。

int ex;
int why;
int zee; //可修改的左值(对象定位值)
const int TWO = 2;//不可修改的左值,但是可初始化
why = 32; //32是右值,不能引用某指定内存位置
zee = why; //可修改的左值
ex = TWO * (why + zee);//表达式是右值,不能表示特定内存位置,而且也不能给它赋值。
/* golf.c -- golf tournament scorecard */
#include <stdio.h>
int main(void)
{int jane, tarzan, cheeta;cheeta = tarzan = jane = 68;//C语言允许三重赋值printf("                  cheeta   tarzan    jane\n");printf("First round score %4d %8d %8d\n",cheeta,tarzan,jane);return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ clang golf.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out cheeta   tarzan    jane
First round score   68       68       68

5.2.2 加法运算符:+

income = salary + bribes;
都是可修改的左值,因为每个变量都标识了一个可被赋值的数据对象。但是表达式是一个右值。

5.2.3 减法运算符:-

+ - 都是二元运算符(binary operator),需要两个运算对象才能完成操作。

5.2.4 符号运算符:-和+

5.2.5 乘法运算符:*

/* wheat.c -- exponential growth 指数增长*/
#include <stdio.h>
#define SQUARES 64             // squares on a checkerboard
int main(void)
{const double CROP = 2E16;  // world wheat production in wheat grainsdouble current, total;int count = 1;printf("square     grains       total     ");printf("fraction of \n");printf("           added        grains    ");printf("world total\n");total = current = 1.0; /* start with one grain   */printf("%4d %13.2e %12.2e %12.2e\n", count, current,total, total/CROP);while (count < SQUARES){count = count + 1;current = 2.0 * current;/* double grains on next square */total = total + current;     /* update total */printf("%4d %13.2e %12.2e %12.2e\n", count, current,total, total/CROP);}printf("That's all.\n");return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ clang wheat.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
square     grains       total     fraction of added        grains    world total1      1.00e+00     1.00e+00     5.00e-172      2.00e+00     3.00e+00     1.50e-163      4.00e+00     7.00e+00     3.50e-164      8.00e+00     1.50e+01     7.50e-165      1.60e+01     3.10e+01     1.55e-156      3.20e+01     6.30e+01     3.15e-157      6.40e+01     1.27e+02     6.35e-158      1.28e+02     2.55e+02     1.27e-14

5.2.6 除法运算符:/

/* divide.c -- divisions we have known */
#include <stdio.h>
int main(void)
{printf("integer division:  5/4   is %d \n", 5/4);printf("integer division:  6/3   is %d \n", 6/3);printf("integer division:  7/4   is %d \n", 7/4);printf("floating division: 7./4. is %1.2f \n", 7./4.);printf("mixed division:    7./4  is %1.2f \n", 7./4);return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
integer division:  5/4   is 1 //整数截断
integer division:  6/3   is 2
integer division:  7/4   is 1
floating division: 7./4. is 1.75
mixed division:    7./4  is 1.75 

5.2.7 运算符优先级

表达式树(expression tree)

5.2.8 优先级和求值顺序

注意正号(加号)和负号(减号)的两种不同用法

5.3 其他运算符

C语言大概有40个运算符

5.3.1 sizeof运算符和size_t类型

sizeof运算符以字节为单位返回运算对象的大小,C语言规定,sizeof返回size_t类型的值,这是一个无符号的整数类型,不是信类型。即C头文件系统使用typedef把size_t作为unsigned int或unsigned long的别名。这样,在使用size_t类型时,编译器会根据不同的系统类型替换标准类型。

C99进一步调整,%zd转换说明用于printf()显示size_t类型的值。

// sizeof.c -- uses sizeof operator
// uses C99 %z modifier -- try %u or %lu if you lack %zd
#include <stdio.h>
int main(void)
{int n = 0;size_t intsize;intsize = sizeof (int);printf("n = %d, n has %zd bytes; all ints have %zd bytes.\n",n, sizeof n, intsize );return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ clang sizeof.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
n = 0, n has 4 bytes; all ints have 4 bytes.

5.3.2 求模运算符:%

求模运算符(modulus operator)用于整数运算,即左侧整数除以右侧整数的余数(remainder)。

// min_sec.c -- converts seconds to minutes and seconds
#include <stdio.h>
#define SEC_PER_MIN 60            // seconds in a minute
int main(void)
{int sec, min, left;printf("Convert seconds to minutes and seconds!\n");printf("Enter the number of seconds (<=0 to quit):\n");scanf("%d", &sec);            // read number of secondswhile (sec > 0){min = sec / SEC_PER_MIN;  // truncated number of minutes截断分钟数left = sec % SEC_PER_MIN; // number of seconds left over剩下的秒数printf("%d seconds is %d minutes, %d seconds.\n", sec,min, left);printf("Enter next value (<=0 to quit):\n");scanf("%d", &sec);}printf("Done!\n");return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ clang min_sec.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
Convert seconds to minutes and seconds!
Enter the number of seconds (<=0 to quit):
154
154 seconds is 2 minutes, 34 seconds.
Enter next value (<=0 to quit):
567
567 seconds is 9 minutes, 27 seconds.
Enter next value (<=0 to quit):
0
Done!

5.3.3 递增运算符:++

递增运算符(increment operator),两种方式,前缀模式(++出现在变量前面)、后缀模式(++出现在变量后面)区别在于递增行为发生的时间不同。

    while (shoe < 18.5)      /* starting the while loop */{                        /* start of block          */foot = SCALE * shoe + ADJUST;printf("%10.1f %15.2f inches\n", shoe, foot);shoe = shoe + 1.0;}                        /* end of block            */while (++shoe < 18.5)      /* starting the while loop */{                        /* start of block          */foot = SCALE * shoe + ADJUST;printf("%10.1f %15.2f inches\n", shoe, foot);}                        /* end of block            */

把控制循环的过程集中在一个地方,但降低了代码的可读性。

其次,递增运算符生成的机器语言代码效率更高。

/* post_pre.c -- postfix vs prefix */
#include <stdio.h>
int main(void)
{int a = 1, b = 1;int a_post, pre_b;a_post = a++;  //使用a的值之后,递增apre_b = ++b;   //使用b的值之前,递增bprintf("a  a_post   b   pre_b \n");printf("%1d %5d %5d %5d\n", a, a_post, b, pre_b);return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
a  a_post   b   pre_b
2     1     2     2

5.3.4 递减运算符:--

#include <stdio.h>
#define MAX 100
int main(void)
{int count = MAX + 1;while (--count > 0) {printf("%d bottles of spring water on the wall, ""%d bottles of spring water!\n", count, count);printf("Take one down and pass it around,\n");printf("%d bottles of spring water!\n\n", count - 1);}return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ clang bottles.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
100 bottles of spring water on the wall, 100 bottles of spring water!
Take one down and pass it around,
99 bottles of spring water!99 bottles of spring water on the wall, 99 bottles of spring water!
Take one down and pass it around,
98 bottles of spring water!1 bottles of spring water on the wall, 1 bottles of spring water!
Take one down and pass it around,
0 bottles of spring water!

5.3.5 优先级

递增和递减运算符只能影响一个变量(只能影响一个可修改的左值)

5.3.6 不要自作聪明

在c语言中,编译器可以自行选择现对函数中的哪个参数求值,这样做提高了编译器的效率,但是如果在函数的参数中使用了递增运算符会出现很多问题,

如果一个变量出现在一个函数的多个参数中,不要对该变量使用递增或递减运算符

如果一个变量多次出现在在一个表达式中,同上

  while (num < 21){printf("%4d %6d\n", num, num * num);num = num + 1;}wlsh@wlsh-MacbookPro] ch05$ clang squares.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out 1      12      43      94     165     256     367     498     649     8110    10011    12112    14413    16914    19615    22516    25617    28918    32419    36120    400
    while (num < 21){printf("%4d %6d\n", num, num * num++);}[wlsh@wlsh-MacbookPro] ch05$ clang squares.c
squares.c:9:43: warning: unsequenced modification and access to 'num' [-Wunsequenced]printf("%4d %6d\n", num, num * num++);~~~           ^
1 warning generated.

5.4 表达式和语句

5.4.1 表达式

表达式(expression)由运算符和运算对象组成,由子表达式(subexpression)组成。但是每个表达式都有一个值。

5.4.2 语句

语句(statement)是C程序的基本构成块,一条语句相当于一条完整的计算机指令。

声明创建了名称和类型,并为其分配内存位置。声明不是一个表达式语句。

/* addemup.c -- five kinds of statements */
#include <stdio.h>
int main(void)                /* finds sum of first 20 integers */
{int count, sum;           /* declaration statement声明          */count = 0;                /* assignment statement           */sum = 0;                  /* ditto表达式语句                          */while (count++ < 20)      /* while迭代语句                          */sum = sum + count;    /*     statement                  */printf("sum = %d\n", sum);/* function statement表达式语句             */return 0;                 /* return statement跳转语句               */
}

副作用(side effect)是对数据对象或文件的修改。

序列点(sequence point)是程序执行的点,在该点上,所有的副作用都在进入下一步之前发生。语句的分号标记一个序列点,意思是,在一个语句中,赋值运算符、递增减运算符对运算对象做的改变必须在程序执行下一条语句之前完成。

    int a = 0;while (a++ < 10)//序列点,保证程序转至执行printf()之前发生副作用。同时,后缀形式保证了a在完成与10的比较后才进行递增。{printf("%d\n",a);}
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
1
2
3
4
5
6
7
8
9
10int a = 0;while (++a < 10){printf("%d\n",a);}
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
1
2
3
4
5
6
7
8
9

5.4.3 复合语句(块)

5.5 类型转换

1.升级(promotion),无论是unsigned还是signed的char和short都会自动转换成int,如有必要会转换成unsigned int。

2.涉及两种类型的运算时,两个值会被分别转换成两种类型的更高级别。

类型级别long double、doubloe 、f'loat、unsignedlong long、long long、unsigned long、long、unsigned int、int

3.当作为函数参数传递时,char和short被转换成int,float转换成double。

4.在赋值表达式语句中,计算的最终结果会被转换成被赋值变量的类型。

/* convert.c -- automatic type conversions */
#include <stdio.h>
int main(void)
{char ch;int i;float fl;fl = i = ch = 'C';                                  /* line 9  */printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); /* line 10 */ch = ch + 1;                                        /* line 11 */i = fl + 2 * ch;                                    /* line 12 */fl = 2.0 * ch + i;                                  /* line 13 */printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); /* line 14 */ch = 1107;                                          /* line 15 */printf("Now ch = %c\n", ch);                        /* line 16 */ch = 80.89;                                         /* line 17 */printf("Now ch = %c\n", ch);                        /* line 18 */return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ clang convert.c
convert.c:17:10: warning: implicit conversion from 'double' to 'char' changes value from 80.89 to 80 [-Wliteral-conversion]ch = 80.89;                                         /* line 17 */~ ^~~~~
convert.c:15:10: warning: implicit conversion from 'int' to 'char' changes value from 1107 to 83 [-Wconstant-conversion]ch = 1107;                                          /* line 15 */~ ^~~~
2 warnings generated.ch = C, i = 67, f1 = 67.00
ch = D, i = 203, f1 = 339.00
Now ch = S
Now ch = P

字符‘c’被作为1字节的ASCII值存储在ch中,整数变量 i 接受由‘C’转换的整数,即按4字节存储67。最后f1接受由67转换的浮点数67.00

字符变量‘C’转换成整数67,然后加1,结果4字节整数68,被截断成1字节存存储在ch中,被解释成‘D’的ASCII码。

然后,为了与f1相加,136转换成浮点数,计算结果(203.00f)转换成int类型,并存储在i中。

再然后,ch的值(68)转换成浮点数,然后2 * ch,为了做加法,i的值(203)转换成浮点类型,计算结果也存储在f1中。

类型降级的示例,把ch设置为一个超出其范围的值,忽略额外的位后,最终ch的值是字符S的ASCII码,确切的说是 1107 % 265 = 83

类型降级的示例,把ch设置位一个浮点数,截断后是字符P的ACSII码。

mice = 1.6 + 1.7
mice = (int)1.6 + (int)1.7

第1行,相加得3.3,为了匹配int类型,3.3被截断为整数3

第2行,相加之前都被转换成整数1,在赋值给mice

5.6 带参数的函数

/* pound.c -- defines a function with an argument   */
#include <stdio.h>
void pound(int n);   // ANSI function prototype declaration
int main(void)
{int times = 5;char ch = '!';   // ASCII code is 33float f = 6.0f;pound(times);    // int argumentpound(ch);       // same as pound((int)ch);
//char与int不匹配,开头的原型(prototype)即函数的声明发挥了作用,描述函数的返回值和参数,
//函数声明告诉编译器pound()需要一个int类型的参数。pound(f);        // same as pound((int)f);return 0;
}void pound(int n)    // ANSI-style function header
{                    // says takes one int argumentwhile (n-- > 0)printf("#");printf("\n");
}
[wlsh@wlsh-MacbookPro] ch05$ clang pound.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
#####
#################################
######

声明创建形式参数(formal argument 或 fromal parameter),函数调用传递的值为实际参数(actual argumeter 或 actual parameter)。

注意:ANSI C之前是函数声明,pound(ch)也没问题,因为即使缺少函数原型,C也会把char和short类型自动升级为int类型。但是pound(f)会失败,因为缺少函数原型,float会被自动升级为double,输出的内容不正确。如下 直接没有了输出

void pound();//函数声明[wlsh@wlsh-MacbookPro] ch05$ clang pound.c
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
#####
#################################

5.7 示例程序

// running.c -- A useful program for runners
#include <stdio.h>
const int S_PER_M = 60;         // seconds in a minute
const int S_PER_H = 3600;       // seconds in an hour
const double M_PER_K = 0.62137; // miles in a kilometer
int main(void)
{double distk, distm;  // distance run in km and in milesdouble rate;          // average speed in mphint min, sec;         // minutes and seconds of running timeint time;             // running time in seconds onlydouble mtime;         // time in seconds for one mileint mmin, msec;       // minutes and seconds for one mileprintf("This program converts your time for a metric race\n");printf("to a time for running a mile and to your average\n");printf("speed in miles per hour.\n");printf("Please enter, in kilometers, the distance run.\n");scanf("%lf", &distk);  // %lf for type doubleprintf("Next enter the time in minutes and seconds.\n");printf("Begin by entering the minutes.\n");scanf("%d", &min);printf("Now enter the seconds.\n");scanf("%d", &sec);// converts time to pure secondstime = S_PER_M * min + sec;// converts kilometers to milesdistm = M_PER_K * distk;// miles per sec x sec per hour = mphrate = distm / time * S_PER_H;// time/distance = time per milemtime = (double) time / distm;mmin = (int) mtime / S_PER_M; // find whole minutesmsec = (int) mtime % S_PER_M; // find remaining secondsprintf("You ran %1.2f km (%1.2f miles) in %d min, %d sec.\n",distk, distm, min, sec);printf("That pace corresponds to running a mile in %d min, ",mmin);printf("%d sec.\nYour average speed was %1.2f mph.\n",msec,rate);return 0;
}
[wlsh@wlsh-MacbookPro] ch05$ ./a.out
This program converts your time for a metric race
to a time for running a mile and to your average
speed in miles per hour.
Please enter, in kilometers, the distance run.
10.0
Next enter the time in minutes and seconds.
Begin by entering the minutes.
36
Now enter the seconds.23
You ran 10.00 km (6.21 miles) in 36 min, 23 sec.
That pace corresponds to running a mile in 5 min, 51 sec.
Your average speed was 10.25 mph.

5.8 关键概念

5.9 小结

第5章 运算符、表达式和语句相关推荐

  1. 《C Primer Plus》第五章-运算符 表达式和语句(笔记、复习题、编程题,副作用和序列点,升降级)

    文章目录 运算符 表达式和语句 本章内容 循环简介 基本运算符 赋值运算符:= 几个术语:数据对象.左值.右值和运算符 加法运算符:+ 减法运算符:- 5.2.4 符号运算符:-和+ 乘法运算符:* ...

  2. 第五章运算符表达式和语句

    title: 第五章 运算符.表达式和语句 author: HardyDragon tags: C Notes 第五章 运算符.表达式和语句 5.1 循环简介 5.2 基本运算符 5.2.1 赋值运算 ...

  3. 【JAVA SE】第三章 运算符、条件语句、switch结构、while循环、do…while循环、for循环、break关键字以及break和continue关键字

    第三章 运算符.条件语句.switch结构.for循环.break关键字以及break和continue关键字 文章目录 第三章 运算符.条件语句.switch结构.for循环.break关键字以及b ...

  4. 《C Prime Plus》(第六版) 第05章 运算符、表达式和语句 例题集和编程练习

    OS: Mac Catalina 10.15.4 Hardware: Intel Core i9/16G 2667MHz DDR4 编译器版本:Mac Xcode 11.6  第05章 运算符.表达式 ...

  5. 《C Primer Plus》中文第六版 编程练习答案 第五章 运算符、表达式和语句

    C Primer Plus 第5章 运算符.表达式和语句 编程练习答案 ***先说一下关于 i++和 ++i 情况.*** 1.编写一个程序,把用分钟表示的时间转换成用小时和分钟表示的时间.使用#de ...

  6. 《C Primer Plus(第6版)中文版》 第5章 运算符、表达式和语句 学习笔记

    对标题和序号稍加修改. 5.1 循环简介 本章仍从一个程序开始. #include<stdio.h> int main(void) {int val=1;while(val<11){ ...

  7. java表达式语句_Java基础知识笔记第三章:运算符表达式语句

    算术运算符与表达式 操作符描述例子 + 加法 - 相加运算符两侧的值 A + B 等于 30 - 减法 - 左操作数减去右操作数 A – B 等于 -10 * 乘法 - 相乘操作符两侧的值 A * B ...

  8. c语言程序设计运算符及表达式,c语言程序设计3第3章运算符和表达式

    1.第3章 运算符和表达式,3.1 表 达 式 3.2 运算符及表达式 3.3 运算符优先级和结合性,3.1 表 达 式,C语言的表达式分为基本表达式和复杂表达式. 基本表达式是由以下单项构成的,即: ...

  9. C语言基础之5:运算符、表达式和语句

    Tips1: 关键字:while.typedef 运算符:=.-.*./.%.++.--.(类型名) C语言的各种运算符,包括用于普通数学运算的运算符 运算符优先级以及语句.表达式的含义 while循 ...

最新文章

  1. ELK(Logstash+Elasticsearch+Kibana)的原理和详细搭建
  2. 洛谷 P1343 地震逃生
  3. 一问就想不起来的问题,来看看?
  4. Fedora下网络配置及相关命令
  5. 索尼笔记本bios如何设置VT-x/AMD-V兼容
  6. java xmpp_Java XMPP负载测试工具
  7. linux服务器做页面,linux服务器搭建在线预览环境
  8. Fiddler在PC/台式对Android进行抓包
  9. NSBundle 的理解和 mainBundle
  10. Nexus 安装 使用说明
  11. pandas—pd.merge通过键来联接数据集
  12. 二叉树三种遍历非递归算法
  13. re模块 match serach findall 详解
  14. 矩形碰撞公式,以前还做j2me时就用到的公式,为了方便查找,这里记一下
  15. 计算公民身份号码校验码(C++)
  16. 百雀羚是如何1天创造380万销售额的?
  17. 小白学习Spring(二)
  18. Java实现子序列问题
  19. JAVA毕业设计健康食谱系统服务器端计算机源码+lw文档+系统+调试部署+数据库
  20. 如何避免危险的免费wifi?

热门文章

  1. mac 安装 Homebrew教程
  2. 测试开发—码流、单码流、双码流、多码流
  3. DIY成本35的自制蓝牙音响
  4. 知道创宇优质混合云解决方案,点击了解~
  5. 区块链重塑经济与世界
  6. GIT部署(三)GIT 远程仓库:添加远程库、从远程库克隆
  7. Android腾讯广告联盟接入-----开屏广告
  8. 关于在安卓M上无法申请 SYSTEM_ALERT_WINDOW 权限的解决方案
  9. h5文件格式数据集制作
  10. cad修改快捷键_CAD入门学习技巧:CAD软件中的CAD快捷键的分类