C语言基础学习day04

运算符、表达式和语句

循环简介

#include <stdio.h>
#define ADJUST 7.31
int main(void)
{
    const double SCALE=0.333;
    double shoe,foot;
    printf("Shoe size (men's) foot length\n");
    shoe=3.0;
    while(shoe<18.5)
    {
        foot=SCALE*shoe+ADJUST;
        printf("%10.1f %15.2f inches\n",shoe,foot);
        shoe=shoe+1.0;
    }
    printf("if the shoe fits,wear it.\n");
    
    return 0;
    
}

当程序第一次到达while循环时,会检查圆括号中的条件是否为真,条件为真,程序进入块中继续执行,把尺码转换成英寸

然后打印计算的 结果。下一条语句把 shoe增加1.0,使shoe的值为4.0:

shoe = shoe + 1.0;
此时,程序返回while入口部分检查条件。

为何要返回while的入口部分?因为上面这条语句的下面是右花括号(}),代码使用一对花括号 ({})来标出while循环的范围。花括号之间的内容就是要被重复执行的内 容。花括号以及被花括号括起来的部分被称为块(block)。现在,回到程序中。因为4小于18.5,所以要重复执行被花括号括起来的所有内容(用计算机术语来说就是,程序循环这些语句)。该循环过程一直持续到shoe的值为19.0。此时,由于19.0小于18.5,所以该条件为假:
shoe < 18.5
出现这种情况后,控制转到紧跟while循环后面的第1条语句。该例中, 是最后的printf()语句。

基本运算符

赋值运算符:=

在编写代码时要记住,=号左侧的项必须是一个变量名。实际上,赋值运算符左侧必须引用一个存储位置。最简单的方法就是使用变量名。不过,后面章节还会介绍“指针”,可用于指向一个存储位置。概括地说,C 使用可修改的左值(modifiable lvalue) 标记那些可赋值的实体。

“项”(如,赋值运算符左侧的项)的就是运算对象(operand)。运算对象是运算符操作的对象。例如,可以把吃汉堡描述 为:“吃”运算符操作“汉堡”运算对象。类似地可以说,=运算符的左侧运算对象应该是可修改的左值

#include<stdio.h>
int main(void)
{
    int jane,tarzan,cheeta;
    cheeta =tarzan =jane =68;
    printf("                  cheeta  tarzan  jane\n");
    printf("first round score %4d %8d %8d\n",cheeta,tarzan,jane);
    
    return 0;
}

许多其他语言都会回避该程序中的三重赋值,但是C完全没问题。赋值 的顺序是从右往左:首先把86赋给jane,然后再赋给tarzan,最后赋给 cheeta

运行结果:

cheeta tarzan jane
first round score 68 68 68

加法运算符:+

加法运算符(addition operator)用于加法运算,使其两侧的值相加。例如,语句:

printf("%d", 4 + 20);

打印的是24,而不是表达式
4 + 20
相加的值(运算对象)可以是变量,也可以是常量。

乘法运算符:*

该程序打印数字1~20及其平方

#include<stdio.h>
int main(void)
{
    int num=1;
    while (num <21)
    {
        printf("%4d%6d\n",num,num*num);
        num=num+1;
    }
    return 0;
}
#include<stdio.h>
#define SQUARES 64
int main(void) 
{
    const double CROP =2E16;
    double current,total;
    int count =1;
    printf("square   grains   total    ");
    printf("fraction  of  \n");
    printf("added     grain     ");
    printf("world             total\n");
    total=current=1.0;
    printf("%4d %13.2e %12.2e %12.2e\n", count,current,total,total/CROP);

    while (count<SQUARES)
    {
        count=count+1;
        current=2.0*current;
        total=total+current;
        printf("%4d %13.2e %12.2e %12.2e\n",count,current,total,total/CROP);
    } 
    printf("That's all.\n");
    
    return 0;
}

当遇到error: stray '\241' in program错误的解决方法:该错误是指源程序中有非法字符,需要将非法字符去掉。一般是由于coder使用中文输入法或者从别的地方直接复制粘贴代码造成的。代码中出现了中文空格,中文引号, 各种中文标点符号都会出现,简单修改一下就OK了

除法运算符:/

#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;

}

运行结果:

注意,整数除法会截断计算结果的小数部分(丢弃整个小数部分),不 会四舍五入结果。混合整数和浮点数计算的结果是浮点数。

实际上,计算机不能真正用浮点数除以整数,编译器会把两个运算对象转换成相同的类型。 本例中,在进行除法运算前,整数会被转换成浮点数。

C99标准以前,C语言给语言的实现者留有一些空间,让他们来决定如何进行负数的整数除法。一种方法是,舍入过程采用小于或等于浮点数的最大整数。当然,对于3.8而言,处理后的3符合这一描述。但是-3.8 会怎样? 该方法建议四舍五入为-4,因为-4 小

于-3.8.但是,另一种舍入方法是直接丢 弃小数部分。这种方法被称为“趋零截断”,即把-3.8转换成-3。在C99以前, 不同的实现采用不同的方法。但是C99规定使用趋零截断。所以,应把-3.8 转换成-3

运算符优先级

#include<stdio.h>
int main(void)
{
    int top,score;
    top=score=-(2+5)*6+(4+3*(2+3));
    printf("top = %d,score = %d\n",top,score);
    return 0;
}

输出结果:-23

sizeof运算符和size_t类型

sizeof运算符以字节为单 位返回运算对象的大小(在C中,1字节定义为char类型占用的空间大小。过去,1字节通常是8位,但是一些字符集可能使用更大的字节

#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;
}

运行结果:

n = 0, n has 4 bytes; all ints have 4 bytes.

C 语言规定,sizeof 返回 size_t 类型的值。这是一个无符号整数类型, 但它不是新类型,size_t是语言定义的标准类型

C有一个 typedef机制,允许程序员为现有类型创建别名。例如,

typedef double real;

这样,real就是double的别名。现在,可以声明一个real类型的变量:
real deal; // 使用typedef

编译器查看real时会发现,在typedef声明中real已成为double的别名,于是把deal创建为double 类型的变量。类似地,C 头文件系统可以使用 typedef 把 size_t 作为 unsigned int 或unsigned long的别名。这样,在使用size_t类型 时,编译器会根据不同的系统替换标准类型

求模运算符:%

负数求模如何进行?C99规定“趋零截断”之前,该问题的处理方法很 多。但自从有了这条规则之后,如果第1个运算对象是负数,那么求模的结 果为负数;如果第1个运算对象是正数,那么求模的结果也是正数:
11 / 5得2,11 % 5得1
11 / -5得-2,11 % -2得1
-11 / -5得2,-11 % -5得-1
-11 / 5得-2,-11 % 5得-1
如果当前系统不支持C99标准,会显示不同的结果。实际上,标准规 定:无论何种情况,只要a和b都是整数值,便可通过a - (a/b)*b来计算a%b。

例如,可以这样计算-11%5:

-11 - (-11/5) * 5 = -11 -(-2)*5 = -11 -(-10) = -1

 递增运算符:++

该运算符以两种方式出现:

第1种方式,++出现在其作用的变量前面, 这是前缀模式;

第2种方式,++出现在其作用的变量后面,这是后缀模式。

#include<stdio.h>
int main(void)
{
    int a=1,b=1;
    int a_post,pre_b;
    a_post=a++;//后缀递增 
    pre_b=++b;//前缀递增
    printf("a   a_post    b   pre_b   \n");
    printf("%1d  %5d  %5d  %5d\n",a,a_post,b,pre_b);
    return 0; 
}

运行结果:

a和b都递增了1,但是,a_post是a递增之前的值,而b_pre是b递增之后 的值。这就是++的前缀形式和后缀形式的区别

x*y++表示的是(x)*(y++),而不是(x+y)++。不过后者无 效,因为递增和递减运算符只能影响一个变量(或者,更普遍地说,只能影 响一个可修改的左值),而组合x*y本身不是可修改的左值。

不要混淆这两个运算符的优先级和它们的求值顺序。假设有如下语句:

y = 2;
n = 3;
nextnum = (y + n++)*6;
nextnum的值是多少?把y和n的值带入上面的第3条语句得:
nextnum = (2 + 3)*6 = 5*6 = 30
n的值只有在被使用之后才会递增为4。根据优先级的规定,++只作用 于n,不作用与y + n。除此之外,根据优先级可以判断何时使用n的值对表达 式求值,而递增运算符的性质决定了何时递增n的值。

如果n++是表达式的一部分,可将其视为“先使用n,再递增”;而++n则表示“先递增n,再使用”。

表达式和语句

表达式

表达式(expression)由运算符和运算对象组成(运算对象是运算符操作的对象)。最简单的表达式是一个单独的运算对象,以此为基础可以建立复杂的表达式

运算对象可以是常量、变量或二者的组合。一些表达式由子 表达式(subexpression)组成(子表达式即较小的表达式)

语句

语句(statement)是C程序的基本构建块。一条语句相当于一条完整的 计算机指令。在C中,大部分语句都以分号结尾 

语句可分为简单语句和复合语句。简单语句以一个分号结尾。

如下所示:

赋值表达式语句:   toes = 12;
函数表达式语句:   printf("%d\n", toes);
空语句:          ;  /* 什么也不做 */
复合语句(或块)由花括号括起来的一条或多条语句组成。

如下面的 while语句所示:
  while (years < 100)
  {
    wisdom = wisdom * 1.05;
    printf("%d %d\n", years, wisdom);
    years = years + 1;
  }

类型转换

基本的类型转换规则

1.当类型转换出现在表达式时,无论是unsigned还是signed的char和short 都会被自动转换成int,如有必要会被转换成unsigned int(如果short与int的大 小相同,unsigned short就比int大。这种情况下,unsigned short会被转换成 unsigned int)。

   在K&R那时的C中,float会被自动转换成double(目前的C不是这样)。由于都是从较小类型转换为较大类型,所以这些转换被称为升级 (promotion)。

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

3.类型的级别从高至低依次是long double、double、float、unsignedlong long、long long、unsigned long、long、unsigned int、int。例外的情况是,当 long 和 int 的大小相同时,unsigned int比long的级别高。

  之所以short和char类型没有列出,是因为它们已经被升级到int或unsigned int。

4.在赋值表达式语句中,计算的最终结果会被转换成被赋值变量的类 型。这个过程可能导致类型升级或降级(demotion)。所谓降级,是指把一 种类型转换成更低级别的类型。

5.当作为函数参数传递时,char和short被转换成int,float被转换成 double。函数原型会覆盖自动升级。
   类型升级通常都不会有什么问题,但是类型降级会导致真正的麻烦。原因很简单:较低类型可能放不下整个数字。例如,一个8位的char类型变量储存整数101没问题,但是存不下22334。

待赋值的值与目标类型不匹配时规则

1.目标类型是无符号整型,且待赋的值是整数时,额外的位将被忽略。 例如,如果目标类型是 8 位unsigned char,待赋的值是原始值求模256。
2.如果目标类型是一个有符号整型,且待赋的值是整数,结果因实现而异。
3.如果目标类型是一个整型,且待赋的值是浮点数,该行为是未定义的

猜你喜欢

转载自www.cnblogs.com/yangyuqing/p/10246018.html
今日推荐