C语⾔关键字解析
在C语⾔中有32个关键字,如下表所⽰:
释:
(1)声明:
1)告诉编译器,这个名字已经匹配到⼀块内存上;
2)告诉编译器,这个名字已经预定了,其他地⽅再也不能⽤它来作为变量名或对象名。
(2)定义:
编译器创建⼀个对象,为这个对象分配⼀块内存空间,并给它取上名字,这个名字就是我们经常所说的变量名或者对象名。
(3)声明和定义的区别:
1)声明可以出现多次,但是定义只能⼀次。
2)定义创建了对象,并为对象分配内存,但是声明只是匹配了⼀块内存,并没有分配内存。
为了⽅便记忆,将关键字分成⼏类:
第⼀类,有关数据“模⼦”的关键字:void、char、short、int、long、float、double、sizeof;
第⼆类,有关数据符号的关键字:signed、unsigned;
第三类,构造类型:struct、union、enum、typedef;
第四类,有关存储与⽣命周期的类型:auto、static、extern、register、const、volatile;
第五类,有关语句的类型:if、else、for、while、do、switch、case、fault、goto、break、continue、return
以下,将主要介绍sizeof、typedef、register、signed和unsigned、volatile、static等关键字。
1、register——最快的关键字
(1)说明:这个关键字请求编译器尽可能的将变量存放在CPU内部的寄存器中,⽽不是通过内存寻址访问以提⾼效率(是尽可能,不是绝对)。
(2)解释:寄存器其实就是⼀块⼀块⼩的存储空间,只不过其存储速度⽐内存快得多,但是价格昂贵。
(3)注意:
1)register变量必须是⼀个单个的值,并且其长度必须⼩于或等于整形的长度。
2)register变量可能不存在内存中,所以不能⽤取地址运算符“&”来获取register变量的地址。
2、static——最名不符实的关键字
(1)说明:声明静态变量。
(2)作⽤:
1)修饰变量:static可以修饰局部变量和全局变量,它们都存放在内部的静态区中。
A、静态全局变量:作⽤域仅限于变量被定义的⽂件中,其他⽂件即使使⽤extern声明也不能使⽤它。准确的说:作⽤域是从定义之处开始到⽂件结束。在定义之处前⾯的那些代码⾏也不能使⽤它,想要使⽤就得在前⾯再加extern***。
B、静态局部变量:作⽤域仅限于该函数⾥,该⽂件中的其他函数也⽤不了。虽然局部变量的⽣命周期随着函数的结束⽽终⽌,但是因为被static修饰的变量总是存在内存的静态区,所以即使这个函数运⾏结束,这个静态变量的值也不会被销毁,函数下次使⽤时仍然能⽤到这个值。
【例1】
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
static int i = 0;
void func1()
{
i = 0;
i++;
}
void func2()
{
static int j = 0;
j++;
}
int main()
{
int k = 0;
for (k = 0; k < 10; k++)
{
func1();
func2();
}
system("pause");
return 0;
}
运⾏结果:
释:
a、每次调⽤func1函数时,i(静态全局变量)都被强制置0, 所以i等于1。
b、虽然调⽤func2函数10次,但是“static int j = 0”语句只被执⾏了⼀次,所以j等于10。
2)修饰函数:函数前⾯加static使得函数成为静态函数,表⽰该函数的作⽤域仅限于本⽂件。好处是:不同的⼈编写不同函数时不⽤担⼼⾃⼰定义的函数是否会与其他⽂件中的函数同名。
3、符号关键字——unsigned和signed
(1)说明:最⾼位如果是1,表明这个数是负数,其值为除最⾼位以外的剩余位的值加上“-”号;最⾼位如果是0,表明这个数是正数,其值为除最⾼位以外的剩余位的值。
【例2】signed char
0000 0001表⽰1;1000 0001表⽰-1。
7—(2
8位的char类型数,其值表⽰的范围为:-27-1)。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
signed char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("% d\n", strlen(a));
system("pause");
return 0;
}
答案是:255。
释:计算机系统中,数值以补码的⽅式来存储。因为⽤补码可以将符号位和其他位统⼀处理,并且减
法和加法都可以⽤补码来处理,当最⾼位(符号位)有进位时,进位将被舍弃。并且,strlen遇“\0”则终⽌。
注意:单纯的char类型应该只⽤于字符值得存储和使⽤;有符号和⽆符号的char类型变量只能⽤于数值的存储和使⽤。
4、const
(1)说明:const是constant的缩写,表⽰恒古不变。被const修饰的变量称为常变量,准确来说应该是只读的变量。
(2)作⽤:
1)修饰只读变量:定义const只读变量,具有不可变性。
static修饰的变量A、const int Max = 100;
释:const修饰的只读变量必须在定义的同时初始化,因为定义后就不能再被改变了。
B、int Array[Max];
释:这样编译时会报错,数组下标只能是常量,即使常变量也不可以,但是宏常数可以。
【问题1】case语句修饰的只读变量必须在定义的同时初始化,为什么?
答:因为case后⾯只能是常量、字符型常量和常量表达式。
2)修饰数组
3)修饰指针
【例3】p可变,p指向的对象不可变
int const *p;//p可变,p指向的对象不可变
int* const p;//p不可变,p指向的对象可变
const int* const p;//p不可变,p指向的对象也不可变
4)修饰函数的参数和返回值
5、volatile—最易变的关键字
(1)说明:volatile是易变、不稳定的意思。
(2)作⽤:⽤volatile修饰的变量可以被某些编译器未知的因素更改,即更新数据,未知的因素如操作系统、硬件或者其他线程等。
【例4】
int i = 10;
int j = i;//1)语句
int k = i;//2)语句
分析:编译时编译器认为i的值没有发⽣变化,所以在1)语句时从内存中取出i的值赋给j后并没有被丢掉,在2)语句时继续⽤这个值给k赋值,⽽不⽣成汇编代码重新从内存⾥取出i的值。
【例5】
volatlie int i = 10;
int j = i;
int k = i;
分析:例2与例1不同的是,volatile关键字告诉编译器,i的值随时可能发⽣变化,则每次⽤i,编译器都会⽣成汇编代码从内存中取i的值。
【问题2】const volatile int i = 10;这⾏代码有没有问题?如果没有,那么i到底是什么属性?
答:没有问题。因为const表⽰常量语义,被const修饰的对象在所在的作⽤域⾥⽆法进⾏修改;volatile表⽰易变的,即在运⾏期对象可能在当前程序上下⽂的控制流以外被修改。发⽣易变的情况,如:在多线程中。被其他线程修改;对象所在的存储器可能被多个硬件设备随机修改等情况。例如,只读的状态寄存器,它是volatile属性,因为它可能被意外的修改。但是,同时它也具有const属性,因为它修饰的内容只能被读⽽不能被写。可知:它们控制的范围不同,被const修饰的对象在程序本⾝内不能修改,⽽被volatile修饰的对象可能在本程序外被修改。所以,const和volatile⼀起使⽤没有问题。
6、sizeof——最冤枉的关键字
(1)说明:sizeof是关键字不是函数,⽤于计算对象的所占的内存⼤⼩。
【例6】sizeof是关键字不是函数
int i = 0;
(A)sizeof(int); (B)sizeof(i); (C)sizeof int; (D)sizeof i;
结果是:在32位系统下,A、B、D的值都为4,⽽C编译出错。
释:sizeof是关键字,带不带括号都可以,但是在int前⾯可以加unsigned和signed,不可以加sizeof。
【例7】计算以形参传递整个数组时的⼤⼩
int b[100];
void fun(int b[100])
{
sizeof(b);
}
结果是:sizeof(b)等于4,即⼀个元素的⼤⼩。
释:数组当形参时,不能将整个数组传值,只能传单个元素。
【例7】有关数组和指针占内存空间⼤⼩的计算
1)int *p = NULL;
sizeof§的值是什么?sizeof(*p)的值⼜是多少?
答:都是4个字节。
2)int a[100];
sizeof(a)的值是多少?//400
sizeof(a[100])呢?//4,因为sizeof只计算,不访问
sizeof(&a)呢?//4
sizeof(&a[0])呢?//4
更多关于sizeof的计算,请访问博客——“”
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论