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循环,但不用 && 和 ||

相关推荐
疯狂打码的少年25 分钟前
【面向对象】设计模式概述(要素、分类:创建型/结构型/行为型)
笔记
懿路向前32 分钟前
【HarmonyOS学习笔记】2026-08-05 | 端插件卡片绑定与跨上下文判断
笔记·学习·ai编程·harmonyos
天空'之城8 小时前
C 语言工业级通用组件手写 24:互补滤波
c语言·开发语言·互补滤波·嵌入式算法·工业级组件
风曦Kisaki11 小时前
Kubernetes(K8s)笔记Day06: 持久化存储(emptyDir,hostPath,NFS),PV 和 PVC,StorageClass存储类
linux·运维·笔记·云原生·容器·kubernetes
wgego16 小时前
基础的反序列化一些总结(php和java)
java·开发语言·笔记
stevenseahang17 小时前
C语言标准演化史:从K&R到GNU,谁才是正统?
c语言·gnu·可移植性·标准演化·ansic
别动我齐刘海17 小时前
Day6 unitree_G1人形机器人GMR—— MotionInput
c语言·c++·人工智能·学习·机器学习·机器人·github
AI科技星18 小时前
曲率‑挠率与 $\boldsymbol{\omega/c}$ 的关系、精算验证及其物理意义
c语言·开发语言·线性代数·算法·决策树·机器学习·ai科技星
依然范特东19 小时前
强化学习笔记6--IS、PPO、TD、DQN、Actor-Critic
笔记·算法
Mxzx品牌21 小时前
佛山招聘软件哪个好:【帅聘网】匹配度高
笔记·其他·生活