声明和定义的区别:
声明是描述对象的类型,用于指代其他地方定义的对象。可以多次声明,内存不为它分配空间,也可声明在多个地方。如:extern arr[];
定义是确定对象的类型并分配内存,用于创建新的对象。 不可多次定义。如:int arr[10];
在C语言中一共有32个关键字,接下来就介绍每一个关键字:
1.auto-------编译器在默认的缺省情况下,所有的变量都是auto的。局部变量都是auto型变量,自动开辟空间,自动回收。
#include<stdio.h>
int main()
{
int num = 0;
int i = 0;
for (i = 0; i < 10; i++)
{
int num = 0;
num++;
printf("%d ", num);//1 1 1 1 1 1 1 1 1 1 (局部变量是auto型变量,开始一次循环,开辟一块空间,一次循环结束自动销毁,下一次循环重新开辟空间。)
}
system("pause");
return 0;
}
2.register-------请求编译器尽可能的将变量存在CPU内部寄存器中而不是通过内存寻址访问以提高效率。
注:使用register修饰符时,变量必须是能被CPU寄存器所接受的类型,这就意味着register变量必须是一个单个的值,并且其长度应小于或等于整型的长度。而且register变 量可能不存放在内存中,所以不能用取址运算符“&”来获取register变量的地址。
3.static-------修饰局部变量,改变的是存储类型,将之前存储在栈中的内容存储到静态区中,存在于函数的整个生命周期,不会被销毁,并且这个变量的值是可以修改的。(局部函数)
#include<stdio.h>
int main()
{
int num = 0;
int i = 0;
for (i = 0; i < 10; i++)
{
static int num = 0;
num++;
printf("%d ", num);//1 2 3 4 5 6 7 8 9 10 (static修饰的变量存储于静态区,并存在于整个函数周期,直到程序结束)
}
system("pause");
return 0;
}
static-------修饰全局变量,改变的是链接属性,将外部变量变成内部变量,作用域仅限于变量被定义的文件中。当具有外部链接属性的标识符(extern)加上static,则将它们具有内部链接属性。(全局函数)
4.short,int,long,char,float,double-------基本数据类型,它们在不同编译器下开辟的内存空间的大小也是不同,
#include<stdio.h>
int main()
{
printf("%d\n", sizeof(short int)); //<span style="color:#ff0000;">2</span>
printf("%d\n", sizeof(int)); //<span style="color:#ff0000;">4
</span> printf("%d\n", sizeof(long int)); //<span style="color:#ff0000;">4</span>
printf("%d\n", sizeof(char)); //<span style="color:#ff0000;">1</span>
printf("%d\n", sizeof(float)); //<span style="color:#ff0000;">4</span>
printf("%d\n", sizeof(double)); //<span style="color:#ff0000;">8</span>
system("pause");
return 0;
}
5.sizeof-------不是函数,是一个关键字,计算变量或类型所占空间的大小。
#include<stdio.h>
int main()
{
int i = 0;
printf("%d\n",sizeof(int));//4
printf("%d\n", sizeof(i));//4
system("pause");
return 0;
}
我们在计算变量的大小时,可以将sizeof后面的括号去掉,但计算类型大小时,因为sizeof和类型(int,float等)都是关键字,所以不能将后面的括号去掉。
#include<stdio.h>
int main()
{
int i = 0;
printf("%d\n", sizeof i);
printf("%d\n", sizeof (i));
printf("%d\n", sizeof int);//sizeof和int都是关键字,出现错误。
printf("%d\n", sizeof (int));
system("pause");
return 0;
}
当sizeof修饰指针变量时
<pre class="objc" name="code">#include<stdio.h>
int main()
{
int arr[10];
printf("%d\n", sizeof(arr)); //40(数组名放入sizeof中,求取的是整个数组的大小,单位是字节)
printf("%d\n", sizeof(&arr)); //4 (取出的是地址,存入到指针变量里,指针变量有4个字节,因为32位平台有32根地址线,组成有32位的信号,构成4个字节)
system("pause");
return 0;
}
sizeof中,表达式是不参与运算的
#include<stdio.h>
int main()
{
int i = 0;;
printf("%d\n", sizeof(i+4-2)); //4(表达式不参与运算,sizeof求取得值依然是i的大小)
system("pause");
return 0;
}
6.signed,unsigned-------有符号数和无符号数,对于一个有符号数来说,最高位是1,表明这个数是负数;最高位是0,表明这个数是正数。
7.if,else
与布尔型的零值进行比较:if(bTestFlag); if(!bTestFlag);
与浮点数的零值进行比较:floatfTestVal = 0; if((fTestVal >= -EPSINON) && (fTestVal <= EPSINON)); //EPSINON 为定义好的精度
与指针变量的零值进行比较: int* p = NULL;//定义指针一定要同时初始化 if(NULL == p); if(NULL != p)
8.switch、case -------当分支结构太多时,使用该语句
注:每个 case 语句的结尾绝对不要忘了加 break,否则将导致多个分支重叠(除非有意使多个分支重叠)。最后必须使用 default 分支。即使程序真的不需要 default 处理,也应该保留 语句:
default:
break;
注:case 后面只能是整型或字符型的常量或常量表达式。
case语句的排列顺序:
按字母或数字顺序排列各条 case 语句。
把正常情况放在前面,而把异常情况放在后面。
按执行频率排列 case 语句。
9.do,while,for-------while循环时,先判断 while 后面括号里的值,如果为真则执行其后面的代码;否则不执行。
break-------表示跳出循环。即循环结束
continue-------表示终止本次(本轮)循环。当 代码执行到 continue 时,本轮循环终止,进入下一轮循环。
注:在多重循环中,如果有可能,应当将长的循环放在内层,短的循环放 在外层,以减少 CPU 跨切循环层的次数。
建议 for 语句的循环控制变量的取值采用“半开半闭区间”写法。半开半闭区间写法和闭区间写法虽然功能是相同,但相比之下,半开半闭区间写法写法更加直观。
循环要尽可能的短,要使代码清晰,一目了然。
10.goto-------只能在函数内部跳转,不能跨函数之间跳转,所以尽量少用该语句。
11.void-------字面意思是“空类型”,void *则为“空类型指针”,void *可以指向任何类型的数据。
注:如果函数没有返回值,那么应声明为 void 类型。
如果函数无参数,那么应声明其参数为 void 。
void 不能代表一个真实的变量。
真正发挥的作用在于: (1) 对函数返回的限定; (2) 对函数参数的限定。
12.return-------用来终止一个函数并返回其后面跟着的值。
注:return 语句不可返回指向“栈内存”的“指针”,因为该内存在函数体结束时 被自动销毁。
13.const-------只读变量,具有不可变性。
修饰一般变量:一般常量是指简单类型的只读变量。这种只读变量在定义时,修饰符 const 可以用在类型说明符前,也可以用在类型说明符后。
例如: int const i=2; 或 const int i=2;
修饰数组:定义或说明一个只读数组
格式: intconsta[5]={1,2,3,4,5};或 constinta[5]={1,2,3,4,5};
修饰指针:const int * p; // p 可变,p 指向的对象不可变(const 修饰*p,p 是指针,*p 是指针指向的对象,不可变 )
int const * p; // p 可变,p 指向的对象不可变 (const 修饰*p,p 是指针,*p 是指针指向的对象,不可变 )
int * const p; // p不可变,p 指向的对象可变(const 修饰 p,p 不可变,p 指向的对象可变)
const int * const p; //指针 p 和 p 指向的对象都不可变( 前一个 const 修饰*p,后一个 const 修饰 p,指针 p 和 p 指向的对象 都不可变)
修饰函数的参数:const 修饰符也可以修饰函数的参数,当不希望这个参数值被函数体内意外改变时使 用。
例如: void Fun(constinti); 告诉编译器 i 在函数体中的不能改变,从而防止了使用者的一些无意的或错误的修改。
修饰函数的返回值:const 修饰符也可以修饰函数的返回值,返回值不可被改变。
14.volatile-------防止编译器对代码进行优化。
15.extern-------可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,下面的代码用到的这些变量或函数是外来的,不 是本文件定义的,提示编译器遇到此变量和函数时在其他模块中寻找其定义。(外部链接属性)
16.struct-------结构体
17.union-------共同体
18.enum-------枚举
enum enum_type_name
{
ENUM_CONST_1,
ENUM_CONST_2, ...
ENUM_CONST_n
} enum_variable_name;
enum 变量类型还可以给其中的常量符号赋值,如果不赋值则会从被赋初值的那个常量开始依次加 1,如果都没有赋值,它们的值从 0 开始依次递增 1。
enum Color
{
GREEN = 1,
RED,
BLUE,
GREEN_RED = 10,
GREEN_BLUE
} ColorVal;
其中各常量名代表的数值分别为:GREEN = 1 RED = 2 BLUE = 3 GREEN_RED = 10 GREEN_BLUE = 11
枚举与#define 宏的区别:
1)#define 宏常量是在预编译阶段进行简单替换。枚举常量则是在编译的时候确定其值。
2)一般在编译器里,可以调试枚举常量,但是不能调试宏常量。
3)枚举可以一次定义大量相关的常量,而#define 宏一次只能定义一个。
19.typedef -------类型重命名,给一个已经存在的数据类型(注意:是类型不是变量)取一个别名,而非定义一个新的数据类型。