您的位置:首页 > 编程语言 > C语言/C++

深入理解C语言关键字

2016-08-13 16:50 169 查看

深入理解C语言关键字

1.C语言中32个关键字



32个关键字 意义

auto 声明自动变量,缺省时编译器一般默认为auto

static 声明静态变量

register 声明寄存器变量

const 声明只读变量

int 声明整形变量

float 声明浮点型变量

char 声明字符型变量

double 声明双精度变量

short 声明短整形变量

long 声明长整形变量

signed 声明有符号类型变量

unsigned 声明无符号类型变量

struct 声明结构体变量

union 声明联合数据类型

enum 声明枚举类型

for 一种循环语句

do 循环语句的循环体

while 循环语句的循环条件

if 条件语句

else 条件语句否定分支(与if连用)

switch 用于开关语句

case 开关语句分支

default 开关语句中的“其它”分支

break 跳出当前循环

continue 结束当前循环,开启下一轮循环

typedef 用以给数据类型取别名(当然还有其他作用)

return 子程序返回语句(可以带参数,也可不带参数)

extern 声明变量是在其他文件正声明(也可以看作是引用变量)

void 声明函数无返回值或无参数,声明空类型指针

goto 无条件跳转语句

volatile 说明变量在程序执行中可被隐含地改变

sizeof 计算对象所占内存空间大小

2.声明和定义的区别:

A) int i;

B) extern int i;

定义:编译器创建一个对象,为这个对象分配一块内存并给它取一个名字,这个名字即变量名/对象名。这个名字和这块内存匹配后就不能再将它们分开。这块内存的位置也不能被改变。 一个变量在一定的区域内(函数内,全局等等)只能被定义一次。

声明:声明有两重含义,

(1):告诉编译器,这个名字已经匹配到一块内存了,下面代码用到的变量是在别的地方定义的。

(2):告诉编译器,这个名字我预定了,别的地方不能再用它来命名了。

>声明可以出现多次, 而定义不能重复。定义创建了对象并为这个对象分配了内存,声明没有分配内存。

3. 关键字register



register这个关键字请求编译器尽可能的将变量存在CPU内部寄存器中,而不是通过内存寻址访问以提高效率。

register变量必须是一个单个的值,其长度不能大于整形的长度, register变量可能不存放在内存中,不能用取址运算符”&”来获取register变量的地址。

register访问速度快,数据从内存里拿出来先放到寄存器,然后CPU再从寄存器里读取数据来处理,处理完后同样把数据通过寄存器存放到内存里,CPU不直接和内存打交道。

4. 关键字static



static修饰变量时,变量被分配在内存的静态区。从定义之处开始,到文件结尾处结束。

静态全局变量的作用域仅限于变量被定义的文件中,其他文件无法使用。

静态局部变量只能在函数里用,当这个函数运行结束时,这个静态变量的值不销毁。

static修饰函数时,函数的作用域局限于本文件。

5.关键字sizeof

sizeof是c/c++中的关键字,它是一个运算符,其作用是取得一个对象(数据类型或数据对象)的长度(即占用内存的大小,以byte为单位)。其中类型包括基本数据类型(不包括void)、用户自定义类型(结构体、类)、函数类型。数据对象是指用前面提到的类型定义的普通变量和指针变量(包含void指针)。

十大特性:

特性0:sizeof是运算符,不是函数;
特性1:sizeof不能求void类型的长度;
特性2:sizeof能求void类型的指针的长度;
其实指针也是变量,只不过这个变量很特殊,它是存放其它变量地址的变量,目前32位计算机平台下的指针变量的大小为4。
特性3:sizeof能求得静态分配内存的数组的长度;
注意:用sizeof求字符串的长度时要加上末尾的‘/0’。
例:

void fun(int array[10])

{

int n = sizeof(array);

}

编辑程序:
#include<iostream>
using namespace std;

int fun(int array[10])
{
int n = sizeof(array);
return n;
}
int main()
{
int ret;
int array[10] = { 0 };
ret = fun(array);
cout << ret << endl;
system("pause");
return 0;
}

运行结果:
4
请按任意键继续. . .

在fun类n的值为4,而不是40,这是因为在函数参数传递时,数组被转化成指针了,假如直接传递整个数组的话,那么必然涉及到数组元素的拷贝(实参到形参的拷贝),当数组非常大时,会导致函数执行效率极低,而只传递数组的地址(即指针),只需要拷贝4byte。

特性4:sizeof不能求动态分配的内存的大小;
特性5:sizeof不能对不完整的数组求长度,否则会编译出错;
特性6:当表达式作为sizeof的操作数时,它返回的是表达式计算结果的类型大小,但是它不对表达式求值;
例:程序:
#include<iostream>
using namespace std;

int main()
{
char ch = 1;
int num = 1;
int n1 = sizeof(ch + num);
int n2 = sizeof(ch = ch + num);
cout << "n1=" << n1 << endl;
cout << "n2=" << n2 << endl;
system("pause");
return 0;
}

结果:
n1=4
n2=1
请按任意键继续. . .

由于默认类型转换的原因,表达式ch + num的计算结果类型为int,因此n1=4;而ch=ch + num的计算结果为char,虽然在计算ch + num时结果为int,当把结果赋给ch时又进行了类型转换,因此表达式的最终类型还是char,故n2=1。

特性7:sizeof可以对函数调用求大小,并且求得的大小等于返回类型(函数类型)的大小,但是不执行函数体;
特性8:sizeof求得的结构体(及其对象)的大小并不等于各个数据成员对象的大小之和;
规则:
a.结构体的大小等于结构体内最大成员大小的整数倍;
b.结构体内的成员的首地址相对于结构体的首地址的偏移量是其类型的整数倍,比如说double型成员相对于结构体的首地址的地址偏移量应该是8的倍数;
c.为了满足规则1和2,编译器会在结构体成员之后进行字节填充;
例:程序:
#include<iostream>
using namespace std;
int main()
{
struct A
{
int num1 = 0;
int num2 = 0;
double num3 = 0;
};

struct B
{
int n1 = 0;
double n2 = 0;
int n3 = 0;
};
cout << "A=" << sizeof(A) << endl;
cout << "B=" << sizeof(B) << endl;
system("pause");
return 0;
}

结果:
A=16
B=24
请按任意键继续. . .

sizeof(A):4+4+8=16
sizeof(B):4(n1占用地址空间:0,1,2,3)+4(不够8的倍数填充4个地址空间,4,5,6,7)+8(n2占用地址空间:8-15)+4(n3占用地址空间:16-19)+4(不够8的倍数填充4个,20,21,22,23)=24。

特性9:sizeof不能用于求结构体的位域成员的大小,但是可以求得包含位域成员的结构体的大小。

例:在32位系统下

#include<iostream>
using namespace std;

void fun(int b[100])
{
cout <<" sizeof(b)=" << sizeof(b) << endl;
}

int main()
{
int *p = NULL;
int a[100];
int b[100];

cout << " sizeof(p)=" << sizeof(p) << endl;
cout << " sizeof(*p)=" << sizeof(*p) << endl;
cout << " sizeof(a)=" << sizeof(a) << endl;
cout << " sizeof(a[100])=" << sizeof(a[100]) << endl;
cout << " sizeof(&a)=" << sizeof(&a) << endl;
cout << " sizeof(&a[0])=" << sizeof(&a[0]) << endl;

fun(b);
system("pause");
return 0;
}


输出:

sizeof(p)=4

sizeof(*p)=4

sizeof(a)=400

sizeof(a[100])=4

sizeof(&a)=4

sizeof(&a[0])=4

sizeof(b)=4

请按任意键继续. . .

>sizeof(a[100])是啥意思?

>函数求值是在运行的时候,sizeof求值是在编译的时候。虽然没有a[100]这个元素,但sizeof(a[100])并不是去访问a[100],而是去识别a这个数组的数组元素的类型.

6.signed和unsigned关键字:

unsigned 都是不小于0的,一个32位的signed int类型整数其值表示范围为:-2^31~2^31 -1;一个32位的unsigned int类型整数其值表示范围为:0~2^32 -1。

编译器缺省默认情况下数据为signed类型的。

7.if语句中的比较

1.bool变量与零值比较:if(bool) ; if(!bool);

2.float变量与零值比较:if(float >= -EPSINON) && (float <= EPSINON);

float变量1与float变量2比较:if(float1 >= float2 - EPSINON) && (float1 <= float2 + EPSINON);

3.指针变量与零值比较:if(NULL == p); if(NULL != p);

使用if else语句时, 应先处理正常情况,再处理异常情况,else总是与最近的if进行匹配。

8. 关键字case



case后的值只能是整形或字符型的常量或常量表达式。

9. switch case 中,不能用continue

多重循环中,应当将最短的循环放到最外层,最长的放到最内层,减少CPU跨切循环层的次数。

注意:break和continue的区别:break终止本层循环,continue只终止本次(本轮)循环。

10.void关键字的作用在于

1.对函数返回的限定;

2.对函数参数的限定;

void *p; 空类型指针可以指向任何类型的数据;

在C语言中,可以给无参数的函数传送任意类型的参数,但在C++中不行;

void a; 这样做,编译器不知道该给a分配多大的空间,不能通过编译。

“空类型”可以包容“有类型”,而“有类型”则不能包容“空类型”。

11. return关键字



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

return 语句不能返回指向栈内存的指针,因为该内存在函数体结束时被自动销毁。

12. const 和 #define 的区别

(1) 编译器处理方式不同

  define宏是在预处理阶段展开。

  const常量是编译运行阶段使用。

(2) 类型和安全检查不同

  define宏没有类型,不做任何类型检查,仅仅是展开。

  const常量有具体的类型,在编译阶段会执行类型检查。

(3) 存储方式不同

  define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。

  const常量会在内存中分配(可以是堆中也可以是栈中)。

(4)const 可以节省空间,避免不必要的内存分配,而宏要进行替换,需要内存分配。

const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而 #define定义的常量在内存中有若干个拷贝。

(5)const 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

(6)const 与 #define的比较优点:

const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。

有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。

13. struct 关键字

0 <= 空结构体的大小 <=最小的结构体的大小 , 空结构体的大小是1.

struct 和 class 的区别:struct 的成员默认情况下属性是public 的,而class 成员却是private 的。struct更适合看成是一个数据结构的实现体,class更适合看成是一个对象的实现体。

14. union关键字

>大端模式:字数据的高字节放到低地址中;小端模式:字数据的高字节放到高地址中。

“大顺小逆”:存放11 22 33 44

高位<------低位

大端:11 22 33 44

小端:44 33 22 11

union型数据所占的空间等于其最大的成员所占的空间。

15. enum关键字



enum 的枚举值必须是整型.

sizeof(enum_type) = sizeof(int);

enum 和 #define 的区别是什么?

(1)#define宏常量是在预编译阶段进行简单替换。枚举常量则是在编译的时候确定其值。

(2)一般在编译器里,可以调试枚举常量,但是不能调试宏常量。

(3)枚举可以一次定义大量相关的常量,而#define宏一次只能定义一个。

16. typedef关键字



typedef是一个存储类关键字,给一个已经存在的数据类型(注意:是类型,不是变量)取一个别名,而非定义一个新的数据类型。

typedef 和 define的区别是什么?

#define支持类型拓展,而typedef取的别名不支持类型拓展。

17.extern关键字

extern可以置于变量或者函数之前,以标示变量或者函数的定义在别的文件中,下面的代码用到的这些变量或函数是外来的,不是本文件定义的,提示编译器遇到此变量和函数时,在其他模块中寻找其定义。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息