变量名
命名限制条件
- 名字是由字母和数字组成的序列,第一个字符必须为字母。
- 变量名不要以下划线“_”开头。
- 大写字母与小写字母要区分(即 x 与 X 是两个不同的名字)。
传统C语言用法中,变量名使用小写字母,符号常量全部使用大写字母。
选择的变量名要能够尽量从字面上表达变量的用途,这样做不容易引起混淆。
局部变量一般使用较短的变量名(尤其是循环控制变量),外部变量使用较长的名字。
数据类型及长度
基本数据类型
char 字符型,占用一个字节,可以存放本地字符集中的一个字符。
int 整型,通常反映了所用机器中整数的最自然长度。
float 单精度浮点型。
double 双精度浮点型。
对基本类型可应用一些限定符,
如
1 short int = short
2 long int = long
3 short一般16比特。
4 int可为16或32比特。
5 long至少是32比特。
6 short类型不得长于int类型,int类型不得长于long类型。
7
8
9 unsigned/signed 修饰char及任何整型。
10 char到底是有符号还是无符号取决于机器实现,但可打印字符总是正值。
11 float/double/long double取决于具体的实现,可以表示相同的长度,也可以表示两种或三种不同的长度。
常量
- int型常量,例1234
- long型常量,例1234l或1234L
- 一个整型常量太大,越出int时,会被当成long对待,例12345678
- 无符号int常量,例1234u或1234U
- 无符号long常量,例1234ul或1234UL
- double常量(无后缀浮点数常量),例123.4或1e-2 (包含小数点或指数,表示为浮点数常量)
- float常量(后缀f或F),例123.4f或1e-2f 或 123.4F或1e-2F
- long double常量(后缀l或L),例123.4l或1e-2l 或 123.4L或1e-2L
- 整数的表达值可为,10进制、8进制或16进制。
-8进制形式:0yyy (yyy表示整型常量)
-16进制形式:0xyyy 或 0Xyyy
-例:
-10进制:31
-8进制:037
-16进制:0x1f或0x1F
-8进制和16进制常量也可以后缀跟 L来表示long,和U来表示unsigned
-例:
-0XFUL表示unsigned long常量值为10进制下的15
-字符常量是整数,单引号内加字符。
-字符常量值是字符在机器的字符集里面的数值。
-例:
-在ASCII字符集,字符常量'0'有值为48。
-字符常量参与数值操作,以整数方式。
-在字符串和字符常量中,特定字符可以被转义序列表达,
-如\n,
-转义字符看起来像是两个字符,但只代表一个。
-此外,任意字节大小的位模式可以被指定,
-通过'\ooo',ooo可以是1个到3个8进制数
-或通过'\xhh',hh可以说一个或多个16进制数。
转义序列集合:
转义字符 | 描述 |
---|---|
\a | 响铃符 |
\b | 回退符 |
\f | 换页符 |
\n | 换行符 |
\r | 回车符 |
\t | 横向制表符 |
\v | 纵向制表符 |
\\ | 反斜杠 |
\? | 问号 |
\’ | 单引号 |
\" | 双引号 |
\ooo | 八进制数 |
\xhh | 十六进制数 |
- 字符常量'\0'代表字符,具有值0,也即null字符。
- 常量表达式是仅仅包含常量的表达式。
- 这样的表达式在编译时求值,而非运行时求值。可以出现在常量可以出现的任何位置。
- 一个字符串常量或字符串文字,是0个或多个被双引号环绕的字符的序列。
- 如:
- "I am a string"
- 或
- "" /* 空字符串 */
- 双引号不属于字符内容,仅用来界定。
- 相同的转义序列,应用于字符常量中的,也应用于字符串。
- \"代表双引号字符。可以将多个字符串常量连接起来。
- "hello, " "world"
- 等价于
- "hello, world"
- 字符串常量是一个字符数组,由空字符'\0'来终止。
- 标准库函数strlen(s) 可以返回字符串参数s的长度,长度不包含末尾的‘\0’。
- 注意区分,一个字符常量和只含一个字符的字符串。
- 例:
- 'x'和"x"
- 前者是一个整数,用于产生字符x在机器字符集里的数值。
- 后者是一个字符数组,包含一个字符,'x',和一个'\0'
- 枚举常量是另外一种类型的常量。
- 枚举是常量整型值的列表。
声明
- 所有变量,在使用前需要声明。
- 特定声明,可能隐含表示。
- 一个声明,指定一个变量类型,且包含一个或多个该类型变量的列表。
- 一个声明语句中的多个变量可以拆开在多个声明语句中声明。
- 一个变量也可能在声明时被初始化。
- 如果声明,跟着一个等号和一个表达式,表达式就相当于一个初始化表达式,
- 如果变量不是自动变量,初始化仅能被执行一次。
- 概念上,在程序开始执行前。且初始化器必须是一个常量表达式。
- 一个显示初始化的自动变量,每次它所在的函数或程序块进入时,都将被初始化一次。
- 且初始化表达式可能是任何表达式。
- 外部变量和静态变量,默认被初始化为0。
- 自动变量,未显式初始化时值为 未定义的值(即无效值)。
- 任何变量的声明都可以使用const限定符限定。该限定符指定变量的值不能被修改。
- 对数组,const也可配合使用,它表明函数不能修改数组元素的值。
- const double e = 2.71828182845905;
算术运算符
- 二元算术运算符: + - * / %(取模运算符)
- %不能被应用于float或double
- 对于整数除法截断方向和对%结果符号,取决于机器。
关系运算符和逻辑运算符
- 关系运算符 > >= < <=
- 相等性运算符 == !=
- 逻辑运算符 && ||
- 由 && 和 || 连接的表达式,按从左到右进行求值,一旦结果已知,求值停止。
- 逻辑非运算符 !,转换一个非0值变为0,一个0变为1
类型转换
- 一个表达式中存在隐士的类型转换,
- 一个表达式包含多项类型时,多个独立的项会被转换为统一的类型再进行运算,
- 常见的包含不同整型或包含整型和浮点时,
- 短整型会向可以包含它的长整型转换,整行会向浮点类型转换。
- char可能被实现为无符号,或有符号类型。
- 可见的字符,在字符集中一般另其最高位为0,故在无符号或有符号实现下,当char转为int时,结果int都是正的。
- 但char中包含其他非可见字符时,最高为1时,在转换为int时,得到的是一个负数还是整数,依赖于char被实现为有符号还是无符号。
- 为了避免这类情形下的不确定,可以显式使用signed char,unsigned char
如果没有unsigned类型的操作数,则只要使用下面这些非正式的规则:
- 如果其中一个操作数的类型为long double ,则将另一个操作数转换为 long double类型;
- 如果其中一个操作数的类型 double,则将另一个操作数转换为 double 类型;
- 如果其中一个操作数的类型 float,则将另一个操作数转换为 float 类型;
- 将 char 与 short 类型的操作数转换为 int 类型;
- 如果其中一个操作数的类型为 long ,则将另一个操作数页转换为 long 类型。
·
- 类型转换,先不考虑有符号和无符号。
- 首先对整型来说,每个整型有存储尺寸,而这在不同机器上是不同的。
- 假设一个运算设计n个整型操作数,
- 其中各个整型数中假设尺寸最大的为类型t。
- 则,
- 第一步,先确定所有操作数的统一类型。
- 原则为:
- 对n个类型进行排序,取出最大类型。
- 所有类型先转化为最大类型再参与运算。
- 排序规则:
- 若类型A尺寸小于类型B尺寸,则A小于B
- 类型A的有符号<类型A的无符号
- 如这样得出的类型尺寸小于int,直接将所有类型转化为int参与运算。
- 对于赋值或者强制类型转换,按指定的目标类型进行转换。
- 出现大类型转到小类型时,存在信息丢失问题。
自增运算符与自减运算符
- 自增运算符++使其操作数递增1,自减运算符--使其操作数递减1。
- 可以用作前缀运算符,也可用作后缀运算符
- 注意的是,++/-- A 或 A ++/-- 作为一个整体是一个表达式,存在一个表达式结果。
- 后++/--版本,整体表达式的值是未被改变的值。而变量值在操作后发生了自增/减1
- 前++/--版本,整体表达式的值是改变后的变量值。变量值在操作后发生了自增/减1
- 自增,自减运算符只能用于变量
位运算符
- 只能作用于整型操作数[带符号或无符号的char/short/init/long]
运算符 | 描述 |
---|---|
& | 按为与(AND) |
| | 按位或 (OR) |
^ | 按位异或 (OR) |
<< | 左移 |
>> | 右移 |
~ | 按位求反(一元运算符) |
/* getbits: get n bits from position p */
// 返回一个unsigned,低n位为x中我们感兴趣的n位。其余位为0。
unsigned getbits(unsigned x, int p, int n)
{
// x >> (p+1-n)把x中不感兴趣的低位移除掉,同时保证此时处理后的unsigned的低n位即为我们感兴趣的
// ~(~0 << n)构造一个unsigned类型数,低n位全部为1,其余部分全部为0
return (x >> (p+1-n)) & ~(~0 << n);
}
赋值运算符和表达式
- 赋值运算符op=
- op可以是:+ - * / % << >> & ^ |
- expr1 op= expr2
- 等价于
- expr1 = (expr1) op (expr2)
- 例子:
x * = y + 1
含义是
x = x * (y+1)
而不是
x = x*y + 1
- 赋值表达式,作为一个整体的类型是左边操作数的类型,结果是复制后的结果。
条件表达
if ( a > b )
z = a;
else
z = b;
/* 用于求a 与 b 中的较大者,并将结果保存到z中 */
条件表达式(使用三元运算符“?:”)提供了另外一种方法编写这段程序及类似的代码段。
expr1 ? expr2 : expr3
在上述表达式中,首先计算expr1 ,如果其值不等于0(为真),则计算expr2的值,并以该值作为条件表达式的值,否则计算expr3的值,并以该值作为条件表达式的值。
expr2与expr3中只能有一个表达式被计算。
上述语句可以改写为:
z = (a > b) ? a : b; /* z = max(a, b) */
如果expr1与expr3的类型不同,结果的类型将由转换规则决定。
例如 :如果 f 为 float 类型,n 为 int类型,那边表达.式
(n > 0)? f : n
是 float 类型,与 n 是否为正值无关。
运算符优先级与求值次序
运算符 | 结合性 |
---|---|
( ) [ ] -> . | 从左至右 |
! ~ ++ – + - * & (type) sizeof | 从右至左 |
* / % | 从左至右 |
+ - | 从左至右 |
<< >> | 从左至右 |
< <= > >= | 从左至右 |
== != | 从左至右 |
& | 从左至右 |
^ | 从左至右 |
| | 从左至右 |
&& | 从左至右 |
|| | 从左至右 |
?: | 从右至左 |
= += -= *= /= %= &= | 从右至左 |
^= |= <<= >>= | 从左至右 |
’ | 从右至左 |
对&& / || / ?: / ,
操作数的求值顺序是被指定的。
/这属于语言陷阱,要避免因此而导致的不确定的代码。
其他运算符的情形下,参与运算的各个操作数的求值顺序是没有明确要求的,取决于实现。
类似的,调用多个形参的函数时,多个实参的求值顺序也是没有明确要求的。
// 该调用,多个实参求值顺序不同时,将产生不一致的结果,是要避免的。
printf("%d %d\n", ++n, power(2, n));
// 左右两边求值顺序不同时,产生不同结果。
a[i] = i++;
参考:
https://blog.csdn.net/x13262608581/article/details/108061295
C程序设计语言 第2版*新版