C语言K&R圣经笔记 2.4声明 2.5算术操作符 2.6关系和逻辑操作符

2.4 声明

所有变量在使用前必须声明,尽管某些特定的声明可以由上下文隐式地做出。声明指定了类型,并包含一个或多个该类型的变量列表,如

复制代码
int lower, upper, step;
char c, line[1000];

多个变量能以任何方式分布在多个声明之中;上面的列表可以等价地写成:

复制代码
int lower;
int upper;
int step;
char c;
char line[1000];

后面一种形式会占用更多空间,但在为每个声明增加注释或是做后续修改时,会很方便。

变量也可以在声明中初始化,如果名字后面跟着一个等号和一个表达式,则表达式作为初始化式(initializer),如

复制代码
char  esc = '\\';
int   i = 0;
int   limit = MAXLINE + 1;
float eps = 1.0e-5;

若该变量不是自动变量,则初始化只会做一次,从概念上来说是在程序执行之前,并且初始化式必须为常量表达式。显式初始化的自动变量,在每次进入其所在的函数或块的时候被初始化。外部和静态变量默认被初始化为0。未显式初始化的自动变量的值是未定义的(即垃圾值)。

修饰符 const 可用于任意变量的声明,以指明它的值不会改变。对数组而言,const 修饰符说明其元素不能被改变。

复制代码
const double e = 2.71828182845905;
const char msg[] = "warning: ";

const 声明也能与数组参数一同使用,以指示函数不会修改数组:

复制代码
int strlen(const char[]);

如果试图修改一个const,其结果是由实现定义的。

2.5 算术操作符

二元算术操作符包括加减乘除 +, -, *, /,以及取模操作符 % 。整数相除会截断小数部分。表达式

复制代码
x % y

得到 x 除以 y 的余数,而当 x 能被 y 整除时就为0。例如,闰年能被4整除而不能被100整除,除非可以被400整除。因此有:

复制代码
if ((year % 4 == 0 && y % 100 != 0) || y % 400 == 0)
    printf("%d is a leap year\n", year);
else
    printf("%d is not a leap year\n", year);

% 操作符不能用于 float 和 double。对于负数,除法 / 的截断方向 和 取模%结果的符号是依赖于机器的,正如发生了上溢和下溢时,所采取的操作也是依赖于机器的。

二元操作符 + 和 - 有相同的优先级,都比 * / 和 % 低,而它们又低于一元操作符正号和符号 + -。算术操作符从左到右结合。

本章结尾的表 2-1总结了所有操作符的优先级和结合性。

2.6 关系和逻辑操作符

关系操作符有

复制代码
    >    >=    <    <=

它们的优先级都相同。优先级仅次于它们的是相等性操作符:

复制代码
    ==    !=

关系操作符的优先级比算术操作符低,因此表达式如 i < lim - 1 就等于 i < (lim -1),符合大家的预期。

更有趣的是逻辑操作符 && 和 || 。由 && 或 || 连接的多个表达式是从左到右求值的,而且一旦结果的真假得到确定就会马上停止求值。大部分的C程序都依赖这两个特性。比如,下面这个循环来自第一章的读取输入的 getline 函数:

复制代码
for (i=0; i<lim-1 && (c=getchar()) != '\n' && c != EOF; ++i)
    s[i] = c;

在读入一个新字符之前,需要检查字符串 s 是否有空间,因此必须先测试 i < lim-1 。 而且如果测试失败,则不能继续读入下一个字符。

类似地,不能在调用getchar之前去检查 c 是否为EOF,因此调用getchar和对c赋值必须发生在检查字符c之前。

&& 的优先级比 || 高,而两者的优先级都低于关系和相等性操作符,因此表达式如

复制代码
 i<lim-1 && (c=getchar()) != '\n' && c != EOF

不需要多余的括号。但由于 != 的优先级高于赋值,因此下面的表达式需要括号

复制代码
    (c = getchar()) != '\n'

以保证先将值赋给c,再和'\n'进行比较。

根据定义,当关系为真时,关系和逻辑表达式的数值为1,当关系为假时值为0。

一元取反操作符 ! 将非0的操作数转换为0,将操作数0 转换为 1。操作符 ! 通常用在这样的结构中:

复制代码
if (!valid)

以取代

复制代码
if (valid == 0)

很难一概而论哪种形式更好。!valid 这种结构读起来更好("如果不合法"),但更复杂的结构会很让人难理解。

练习2-2,重写上面的for循环,但不用 && 和 ||

相关推荐
三水不滴9 分钟前
Redis 过期删除与内存淘汰机制
数据库·经验分享·redis·笔记·后端·缓存
梵刹古音1 小时前
【C语言】 函数基础与定义
c语言·开发语言·算法
梵刹古音1 小时前
【C语言】 结构化编程与选择结构
c语言·开发语言·嵌入式
wdfk_prog1 小时前
[Linux]学习笔记系列 -- [drivers][i2c]i2c-dev
linux·笔记·学习
土拨鼠烧电路1 小时前
笔记03:业务语言速成:“人、货、场”模型与IT系统全景图
笔记
爱编码的小八嘎2 小时前
C语言对话-22.想睡觉,偶然
c语言
2301_812731412 小时前
CSS3笔记
前端·笔记·css3
小乔的编程内容分享站3 小时前
记录使用VSCode调试含scanf()的C语言程序出现的两个问题
c语言·开发语言·笔记·vscode
蓁蓁啊3 小时前
C/C++编译链接全解析——gcc/g++与ld链接器使用误区
java·c语言·开发语言·c++·物联网
中屹指纹浏览器4 小时前
2026年指纹浏览器技术迭代与风控对抗演进
经验分享·笔记