C语言深度解剖读书笔记1

关键字 意义 关键字 意义
auto 声明自动变量,缺省时编译器一般默认为auto register 声明寄存器变量
int 声明整型变量 const 声明只读变量
double 声明双精度变量 volatile 说明变量在程序执行中可被隐含地改变
long 声明长整型变量 typedef 用以给数据类型取别名(当然还有其他作用)
char 声明字符型变量 extern 声明变量是在其他文件中声明(也可以看作是引用变量)
float 声明浮点型变量 return 子程序返回语句(可以带参数,也可以不带参数)
short 声明短整型变量 void 声明函数无返回值或无参数,声明空类型指针
signed 声明有符号类型变量 continue 结束当前循环,开始下一轮循环
unsigned 声明无符号类型变量 do 循环语句的循环体
struct 声明结构体变量 while 循环语句的循环条件
union 声明联合数据类型 if 条件语句
enum 声明枚举类型 else 条件语句否定分支(与if连用)
static 声明静态变量 for 一种循环语句
case 开关语句分支 goto 无条件跳转语句
default 开关语句中的其他分支 sizeof 计算对象所占内存空间大小
break 跳出当前循环 switch 用于开关语句

部分关键字说明

register

register变量必须是能被CPU寄存器接受的类型。意味着register变量必须是单一的值,长度<=整型长度,且register变量可能不存放在内存中,所以不能用 “&” 来获取它的地址。

static

作用1:修饰变量。变量又分为局部变量和全局变量,但它们都存在内存的静态区。
作用2:修饰函数。函数前加static使得函数成为静态函数。此处static指对函数的作用域仅限于本文件。

静态全局变量,作用城仅限于变量被定义的文件中,其他文件即使用extern声明也没法使用它。准确的说:作用城是从定义之处开始,到文件结尾处结束,在定义之处前面的那些代码行也不能使用它。
静态局部变量,在函数体里面定义的,就只能在这个函数里用了,同一个文档中的其他函数也用不了。由于被static修饰的变量总是存在内存的静态区,所以即使这个函数运行结束,这个静态变量的值也不会被销毁,函数下次使用时仍然能用到这个值。

sizeof

sizeof在计算变量所占空间大小时,括号可以省略,而计算类型(模子)大小时不能省略。且一般情况下,sizeof是在编译时求值,所以sizeof(i++)不会引起副作用。由于sizeof(i++)与sizeof(i)结果一样,所以没必要也不允许写这样的代码。同样,sizeof(i=1234); 也不允许,因为 i 的值还是0,没有改变。
用sizeof计算字符串长度时会算上‘\0’。

if、else

bool变量与“零值”的比较:
if语句写法:

bool bTestFlaf = FALSE ;
//  if(bTestFlaf);这种写法不会引起误会
//  if(!bTestFlaf);

float变量与“零值”的比较:
if语句写法:

float fTestVal = 0.0;
if((fTestVal >= - EPSINON) && (fTestVal <= - EPSINON) );
//EPSINON为定义好的精度

指针变量与“零值”的比较:
if语句写法:

int *p = NULL;//定义指针一定要初始化
//if(NULL == p);
//if(NULL != p);

else到底与哪个if配对
else始终与同一括号内最近的未匹配的if语句结合。

使用if语句的其他注意事项

  • 先处理正常情况,再处理异常情况。
  • 确保if和else子句没有弄反。
  • 赋值运算符不能使用在布尔值的表达式上。
  • 所有的if-else if结构应该由else子句结束。

case

  • case后面只能是整型或字符型的常量或常量表达式。
  • case后面的代码尽量不要超过20行。
  • 不要为了使用case语句而刻意制造一个变量。
  • 将default子句只用于检查真正的默认情况。

void

void的字面意思是“空类型”,void *则为“空类型指针”,void *可以指向任何类型的数据。void 几乎只有“注释”和限制程序的作用。但是是可以定义一个void变量。
void真正用:对函数返回的限定;对函数参数的限定。
众所周知,如果指针P1和P2的类型相同,那么我们可以直接在P1和P2间互相赋值;如果P1和P2指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边指针的类型转换为左边指针的类型。例如:

float *p1;
int *p2;
p1 = (float *)p2;

而void * 不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换:

void *p1;
int *p2;
p1 = p2;

但这并不意味着,void*也可以无需进行强制类型转换地赋给其他类型的指针,因为“空类型”可以包容“有类型”,而“有类型”则不能包容“空类型”。

void *p1;
int *p2;
p2 = p1;//编译出错

提示“‘=’:cannot convert from ‘void *’ to ‘int *’ "。

void修饰函数返回值和参数

  • 如果函数没有返回值,那么应将其声明为void类型。
    在C语言中,凡不加返回值类型限定的函数,就会被编译器作为返回整型值处理。
  • 如果函数无参数,那么应声明其参数为void。
  • 如果函数的参数可以是任意类型指针,那么应该声明其参数为void *。

void不能代表一个真实的变量

const

定义const只读变量,具有不可变性。

  • 节省空间,避免不必要的内存分配,同时提高效率。
    编译器通常不为普通const分配存储空间,而是保存在符号表中,成为编译
    期间的值,没了存储与读内存的操作,使之效率很高。
    const定义的只读变量从汇编的角度来看,只是给出了对痖的内存地址。而不
    是像#define一样给出的是立即数,所以,const定义的只读变量在程序运行过程中只有一份备份(因为它是全局的只读变量,存放在静态区),而# define定义的宏常量在内存中有若千个备份。 #define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。#define宏没有类型,而const修饰的只变量具有特定的类型。
  • 修饰一般变量。
  • 修饰数组。
  • 修饰指针。
  • 修饰函数的参数。
void Fun(const int *p);
  • 修饰函数的返回值。
const int Fun(void);

小知识点

浮点型标准

使用浮点数应遵循已定义好的浮点数标准:
在表示浮点数的各个字节中,究竟用多少位表示小数部分,多少位表示指数部分,标准C中无具体定义。
ANSI/IEEE标准的基本规定如下所述。

  • 两种基本浮点格式:单精度和双精度。
  • 两种扩展浮点格式:单精度扩展和双精度扩展。
  • 浮点运算的准确度要求:加、减、乘、除、平方根、余数、将浮点格式的数舍人为整数值、在不同浮点格式之间转换、在浮点和整数格式之间转换以及比较。
  • 在十进制字符串和两种基本浮点格式之-一的二进制浮点数之间进行转换的准确度.单- -性和一致性要求。
  • 五种类型的IEEE浮点异常,以及用于向用户指示发生这些类型异常的条件。
    五种类型的浮点异常是:无效运算、被零除、上溢、下溢和不精确。
  • 四种射入方向:
    ①向最接近的可表示的值;
    ② 当有两个最接近的可表示的值时,首选“偶数”值;
    ③向负无穷大(向下);
    ④向正无穷大(向上)以及向0(截断)。

以0开头的数字被认为八进制格式的数

禁止使用八迸制的常数 (0除外,因カ严格意义上来讲0也是八迸制数) 和八迸制的转义字符。
在计算机中,任何以0开头的数字都被认为是八迸制格式的数(当然十六进制的0x不算)。所以,当我们写固定长度的数字时,会存在一定的风险。举例如下:

 code[1] = 109;//对应十迸制的109
 code[2] = 100;//对应十迸制的100
 code[3] = 052;//对应十迸制的42,因为052是以0开头,以八进制形式存储
 code[4] = 071;//对应十迸制的57

在转义字符中后面跟八迸制数,用于表示ASClI码等于该值的字符,使用时也可能会出现意想不到的错误。

code[5] = ‘\109';
/*可能代表两个字符,‘\10’后面的9因为超出八进制表示范围,被看作字符“9”*/

case后不能加const修饰的常量

#include <stdio.h>
int main()
{
	int const a = 4;
	int m = 0;
	scanf("%d",&m);
	
	switch(m)
	{
		case a:
			printf("m = %d\n",a);
			break;
		default:
			printf("m != %d\n",a);
			break;
	}
	
	return 0;
}

运行报错
In function ‘main’:
error: case label does not reduce to an integer constant
case a:

在switch case 语句中能否使用continue 关键字?

continue语句与break语句使用场合类似,continue语句是不可以在单独的switch语句中使用,但可以在一个循环内的switch语句中使用

  1. 不能。

  2. continue语句一般形式为"continue"。

  3. 其作用为结束本次循环。即跳出循环体中下面尚未执行的语句,对于while循环,继续求解循环条件。而对于for循环程序流程接着求解for语句头中的第三个部分expression表达式。

  4. continue语句的作用是跳过循环本中剩余的语句,并到循环末尾。

  5. continue语句只用在for、while、do-while等循环体中, 常与if条件语句一起使用, 用来加速循环。

猜你喜欢

转载自blog.csdn.net/weixin_43665091/article/details/84839510