C语言深度解剖——关键字

一、auto关键字

在缺省情况下,编译默认的所有变量都是auto。


二、register关键字

使用该关键字是让编译器尽可能把变量存在CPU的内部寄存器中,而不是内存寻址访问,从而提高了效率。之所以说是尽可能,是因为CPU的寄存器是有限的,如果用register修饰的变量超过了CPU的寄存器,CPU也不能把全部的变量都放在寄存器中。那什么是寄存器?寄存器就是一块一块的存储空间,它能直接和CPU打交道,内存却不行,因此寄存器的存取速率要大于内存。


三、static关键字

1、static修饰变量,包括全局变量和局部变量,且修饰的变量都是存在内存的静态存储区。

(1)、static修饰全局变量:用static修饰的全局变量只能在变量被定义的文件中使用,其它文件不能使用,而且在变量定义的地方前面的代码是不能使用该变量的,只有后面的代码才能使用。

(2)、static修饰局部变量:用static修饰的局部变量是存储在静态存储区的,因此即使是函数运行结束,这个静态变量值也不会被销毁,函数下次使用时会继续使用该值。

#include <stdio.h>
#include <stdlib.h>

void test_fun1(void)
{
    int value1 = 0;
    value1++;
    printf("value1:%d\n", value1);
}

void test_fun2(void)
{
    static int value2 = 0;
    value2++;
    printf("value2:%d\n", value2);
}

void test_fun3(void)
{
   int i = 0;

   for (i=0; i<10; i++)
   {
        test_fun1();
        test_fun2();
   }
}

int main(void)
{
    test_fun3();

    return 0;
}

结果:

value1:1
value2:1
value1:1
value2:2
value1:1
value2:3
value1:1
value2:4
value1:1
value2:5
value1:1
value2:6
value1:1
value2:7
value1:1
value2:8
value1:1
value2:9
value1:1
value2:10

2、static修饰函数,用static修饰的函数并不是指存储形式,而是指修饰的函数只能在本文件中使用,这样做的好处是当多人合作时,不用担心自己写得函数会和别人写的函数同名而有冲突。


四、基本数据类型

1、short:在32位系统上,short的内存大小是2字节。

2、int:在32位系统上,int的内存大小是4字节。

3、long:在32位系统上,long的内存大小是4字节。

4、float:在32位系统上,float的内存大小是4字节。

5、double:在32位系统上,double的内存大小是8字节。

6、char:在32位系统上,char的内存大小是1字节。


五、sizeof关键字

1、一般情况一下sizeof是在编译的时候求值,而在C99中计算柔性数组所占用的空间是,sizeof是在运行时求值的。(C语言柔性数组讲解)。

2、sizeof不是函数。

3、举例:

int a = 0;
sizeof(int); //计算结果为4
sizeof(a); //计算结果为4
sizeof int; //编译出错
sizeof a; //计算结果为4

4、sizeof(int)*p表示什么意思?


六、signed、unsigned

1、负数存储方法:把数据类型的最高位用来存储符合,如果最高位为1,则表示这个数是负数;如果最高位为0,则表示这个数是正数。


七、if、else组合

1、else始终与统一括号内最近为匹配的if匹配。

2、在编程时,将正常情况放在if后面处理,将异常情况放在else后面处理。


八、switch、case组合

1、if、else一般在嵌套比较少的分支使用,如果分支多使用switch、case能提高效率。

2、case语句结果要用break结束,否则会导致分支重叠。

3、最后必须使用default分支,即使不需要在defalut里面处理,也应该保留:

defalut:
	break;

4、switch、case组合中禁止使用return

5、case后面只能是整型或者字符型的常量或者常量表达式。


九、do、while、for

1、while循环:先判断while括号里面的值是否为真,如果为真则执行后面的代码。

2、do-while循环:先执行一遍do里面的代码,再判断while括号的值是否为真,如果为真则继续执行do里面的代码。

3、for循环:用于实现知道循环次数的循环,且循环次数可控制。

4、breakcontinue的区别:break表示终止本层循环,continue表示结束本次循环,进入下一次循环。

例如:

int i = 0;
bool bFlag = FALSE;

for (i=0; i<10;i++)
{
	if (5 == i) //i等于5的时候,结束for循环,循环执行了5次,打印了5次“Hello World”
	{
		break;
	}
	printf("Hello World\n");
}


for (i=0; i<10;i++)
{
	if (5 == i)//i等于5时,结束本次循环,不结束for循环,且i等于5的时候,不执行打印“Hello World”,i不等于5的时候才执行打印"Hello World",循环执行了10次
	{
		continue;
	}
	printf("Hello World\n");
}

5、在多重for循环中,如果可能,应该将最长的循环放在最内层,最短的循环放在最外层,减少CPU切换循环层的次数。
例如:

//效率高
for (col=0; col<5; col++)
{
    for (row=0; row<100; row++)
    {
        sum = sum + a[row][col]
    }
}

//效率低
for (row=0; row<100; row++)
{
    for (col=0; col<5; col++)
    {
        sum = sum + a[row][col]
    }
}

6、在for循环,建议使用半开半闭区间写法。
例如:

//半开半闭区间写法
for (n=0; n<10; n++)
{

}

//闭区间写法
for (n=0; n<=9; n++)
{

}

7、for循环控制表达式不能包含任何浮点类型的对象。控制表达式一般会包含一个计数器,检测计数器的值来判断是否终止循环,而浮点变量在舍入和截取误差的时候会通过循环迭代过程传播,导致循环变量的显著误差,从而在检测的时候可能导致不可预期的结果。


十、goto关键字

goto语句虽然可以灵活跳转,但是如果不加以限制,会破坏结构化设计风格,存在很大的隐患,因此在程序设计的时候,应该尽量不用goto


十一、return关键字

1、return用来终止终止一个函数并返回其后面跟着的值。

2、return不可返回指向栈内存的指针,因为栈内存在函数接收的时候就被自动回收销毁了。
例如:

char * fun(void)
{
	char str[30];
	
	...

	return str;
}

3、return;的作用:用于返回值类型是void的函数,强制结束当前函数。
例如:
只打印“Hello”,不打印“World”。

void fun(void)
{
	printf("Hello");
	return;
	printf("World");
}

十二、const关键字

1、const修饰的变量必须在定义的时候初始化。

2、case后面不能是const修饰的只读变量。因为case后面只能跟整形或者字符型的常量或常量表达式;而C语言中const 修饰的是只读变量,具有不可变型,而且const修饰的只读变量只能在定义的时候初始化,不能定义后再赋值。

3、编译器通常不为普通const变量分配存储空间,而是将它们保存在符合表中,这样使它成为一个编译期间的值,没有了存储和读内存的操作。
例如:

#define M 3			//宏常量
const int N = 5;	//此时未将N放入内存中

int i = N;			//此时为N分配内存,以后不再分配
int I = M;			//预编译期间进行宏替换,分配内存
int j = N;			//没有内存分配
int J = M;			//再进行宏替换,再进行一次内存分配

4、const修饰指针

const int *p;	//p可变,p指向的对象不可变
int const *p;	//p可变,p指向的对象不可变
int *const p;	//p不可变,p指向的对象可变
const int *const p;	//p不可变,p指向的对象不可变

5、const修饰函数的参数

//*p在函数体内不能被修改。
void fun(const int *p)

十三、volatile关键字

1、volatile的作用是“告诉编译器,i是随时可能发生变化的,每次使用它的时候必须从内存中取出i的值”。


十四、union关键字

1、大小端模式端union类型数据的影响。

大端模式:字数据的高字节存在低地址中,低字节存在高地址中。
小端模式:字数据的高字节存在高地址中,低字节存在低地址中。
在这里插入图片描述
union所占的空间大小等于其最大成员空间大小。

2、编写程序,判断处理器是大端模式还是小端模式。

//返回1则是小端模式
//返回0这是大端模式
int checkCPU(void)
{
	union check
	{
		int a;
		char b;
	}ucheck;

	ucheck.a = 1;
	return (ucheck.b == 1);
}

参考文献

《C语言深度解剖》

发布了54 篇原创文章 · 获赞 92 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Sanjay_Wu/article/details/103574754