网站首页 > 基础教程 正文
一、类型转换
通常, 在语句和表达式中应使用类型相同的变量和常量。 但是, 如果使用混合类型, C 不会像 Pascal那样停在那里死掉, 而是采用一套规则进行自动类型转换。 虽然这很便利, 但是有一定的危险性, 尤其是在无意间混合使用类型的情况下(许多UNIX系统都使用lint程序检查类型“冲突”。 如果选择更高错误级别, 许多非UNIX C编译器也可能报告类型问题) 。 最好先了解一些基本的类型转换规则。
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。
下面的程序示例则很好的演示了这些规则:
/* convert.c -- 自动类型转换 */
#include <stdio.h>
int main(void)
{
char ch;
int i;
float fl;
fl = i = ch = 'C'; /* 第9行 */
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); /* 第10行 */
ch = ch + 1; /* 第11行 */
i = fl + 2 * ch; /* 第12行 */
fl = 2.0 * ch + i; /* 第13行 */
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl); /* 第14行 */
ch = 1107; /* 第15行 */
printf("Now ch = %c\n", ch); /* 第16行 */
ch = 80.89; /* 第17行 */
printf("Now ch = %c\n", ch); /* 第18行 */
return 0;
}
运行convert.c后输出如下:
ch = C, i = 67, fl = 67.00
ch = D, i = 203, fl = 339.00
Now ch = S
Now ch = P
在我们的系统中, char是8位, int是32位。 程序的分析如下。
第9行和第10行: 字符'C'被作为1字节的ASCII值储存在ch中。 整数变量i接受由'C'转换的整数, 即按4字节储存67。 最后, fl接受由67转换的浮点数67.00。
第11行和第14行: 字符变量'C'被转换成整数67, 然后加1。 计算结果是4字节整数68, 被截断成1字节储存在ch中。 根据%c转换说明打印时, 68被解释成'D'的ASCII码。第12行和第14行: ch的值被转换成4字节的整数(68) , 然后2乘以ch。为了和fl相加, 乘积整数(136) 被转换成浮点数。 计算结果(203.00f) 被转换成int类型, 并储存在i中。
第13行和第14行: ch的值('D', 或68) 被转换成浮点数, 然后2乘以ch。 为了做加法, i的值(203) 被转换为浮点类型。 计算结果(339.00) 被储存在fl中。第15行和第16行: 演示了类型降级的示例。 把ch设置为一个超出其类型的值, 忽略额外的位后, 最终ch的值是字符S的ASCII码。 或者, 更确切地说, ch的值是1107 % 265, 即83。第17行和第18行: 演示了另一个类型降级的示例。 把ch设置为一个浮点数, 发生截断后, ch的值是字符P的ASCII码。
二、循环
(1)再探while循环
/* summing.c -- 根据用户键入的整数求和 */
#include <stdio.h>
int main(void)
{
long num;
long sum = 0L; /* 把sum初始化为0 */
int status;
printf("Please enter an integer to be summed ");
printf("(q to quit): ");
status = scanf("%ld", &num);
while (status == 1) /* == 的意思是“等于” */
{
sum= sum + num;
printf("Please enter next integer (q to quit): ");
status = scanf("%ld", &num);
}
printf("Those integers sum to %ld.\n", sum);
return 0;
}
该程序使用long类型以储存更大的整数。 尽管C编译器会把0自动转换为合适的类型, 但是为了保持程序的一致性, 我们把sum初始化为0L(long类型的0) , 而不是0(int类型的0) 。该程序的运行示例如下:
Please enter an integer to be summed (q to quit): 44
Please enter next integer (q to quit): 33
Please enter next integer (q to quit): 88
Please enter next integer (q to quit): 121
Please enter next integer (q to quit): q
Those integers sum to 286.
现在我们来看一下该程序的结构:
现在, 我们来看看该程序的结构。 总结如下:
把sum初始化为0
提示用户输入数据
读取用户输入的数据
当输入的数据为整数时,
输入添加给sum,
提示用户进行输入,
然后读取下一个输入
输入完成后, 打印sum的值
顺带一提, 这叫作伪代码(pseudocode) , 是一种用简单的句子表示程序思路的方法, 它与计算机语言的形式相对应。 伪代码有助于设计程序的逻辑。 确定程序的逻辑无误之后, 再把伪代码翻译成实际的编程代码。 使用伪代码的好处之一是, 可以把注意力集中在程序的组织和逻辑上, 不用在设计程序时还要分心如何用编程语言来表达自己的想法。 例如, 可以用缩进来代表一块代码, 不用考虑C的语法要用花括号把这部分代码括起来。
while循环的通用形式如下:
while ( expression )
statement
statement部分可以是以分号结尾的简单语句, 也可以是用花括号括起来的复合语句。
到目前为止, 程序示例中的expression部分都使用关系表达式。 也就是说, expression是值之间的比较, 可以使用任何表达式。 如果expression为真(或者更一般地说, 非零) , 执行 statement部分一次, 然后再次判断expression。 在expression为假(0) 之前, 循环的判断和执行一直重复进行。每次循环都被称为一次迭代(iteration) , 如图所示。
使用while时, 要牢记一点: 只有在测试条件后面的单独语句( 简单语句或复合语句) 才是循环部分。 程序清单6.3演示了忽略这点的后果。 缩进是为了让读者阅读方便, 不是计算机的要求。
while循环经常依赖测试表达式作比较, 这样的表达式被称为关系表达式(relational expression) , 出现在关系表达式中间的运算符叫做关系运算符(relational operator) 。 关系运算符常用于构造while语句和其他C语句(稍后讨论) 中用到的关系表达式。 这些语句都会检查关系表达式为真还是为假。 下面有3个互不相关的while语句, 其中都包含关系表达式。
while (number < 6)
{
printf("Your number is too small.\n");
scanf("%d", &number);
}
while (ch != '#39;)
{
count++;
scanf("%c", &ch);
}
while (scanf("%f", &num) == 1)
sum = sum + num;
注意, 第2个while语句的关系表达式还可用于比较字符。 比较时使用的是机器字符码(假定为ASCII) 。 但是, 不能用关系运算符比较字符串。
虽然关系运算符也可用来比较浮点数, 但是要注意: 比较浮点数时, 尽量只使用<和>。 因为浮点数的舍入误差会导致在逻辑上应该相等的两数却不相等。 例如, 3乘以1/3的积是1.0。 如果用把1/3表示成小数点后面6位数字, 乘积则是.999999, 不等于1。 使用fabs()函数(声明在math.h头文件中)可以方便地比较浮点数, 该函数返回一个浮点值的绝对值(即, 没有代数符号的值) 。
(2)什么是真?
这是一个古老的问题, 但是对C而言还不算难。 在C中, 表达式一定有一个值, 关系表达式也不例外。 程序中的程序用于打印两个关系表达式的值, 一个为真, 一个为假。
/* t_and_f.c -- C中的真和假的值 */
#include <stdio.h>
int main(void)
{
int true_val, false_val;
true_val = (10 > 2); // 关系为真的值
false_val = (10 == 2); // 关系为假的值
printf("true = %d; false = %d \n", true_val, false_val);
return 0;
}
程序把两个关系表达式的值分别赋给两个变量, 即把表达式为真的值赋给true_val, 表达式为假的值赋给false_val。 运行该程序后输出如下:
true = 1; false = 0
猜你喜欢
- 2024-10-22 C语言标准库所包含的函数功能介绍(2)
- 2024-10-22 C语言矩阵库 c语言 矩阵运算库
- 2024-10-22 使用树莓派做两轮自平衡车(二)——获取角度
- 2024-10-22 C语言系统编程——函数的使用 c语言中函数的使用方法
- 2024-10-22 C语言学习之-----(六) 条件语句 c语言的条件运算
- 2024-10-22 C 语言中比较浮点数值 c语言如何比较两个浮点数相等
- 2024-10-22 C语言程序设计(谭浩强第五版) 第5章 循环结构程序设计 习题解析答案
- 2024-10-22 c语言入门12,看书都懂,真让写代码却不知道如何入手咋办
- 2024-10-22 C语言基础知识(回顾篇) c语言基础知识入门知识点
- 2024-10-22 7.Python趣味数学笔记:三维向量及其运算
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)