原创 const、define、volatile、空指针等使用注意事项

2012-9-13 12:51 2298 9 9 分类: 软件与OS 文集: C语言深度解剖

1.在C语言中,const修饰的变量,表示只读变量,仍为变量,只是属性为只读。定义时必须初始化。所以不能用在初始化数组个数和case语句后面,因为它们要求为常量,常量表达式;但在C++程序中则可以,C++中扩展了const的含义。

在1.cpp中程序编译正确。

void main(void)

{

    const int n=20;

    int a[n];

    int i=0;

    switch (i)

    {

    case n:break;

    default:

        break;

    }

    while (1);

}

 

1.jpg

而改为1.c重新编译

输出结果如下:

 

2.jpg

2.const修饰的只读变量在编译时确定其值,有特定的数据类型;而#define宏定义,define不是关键字,在预编译时进行替换,没有类型。编译器不为普通const只读变量分配内存空间,将它们保存在符号表中,使其成为一个编译期间的值,没有存储与读内存的操作,效率高。(?)

#define M 3

const int N = 5; //此时并未把N放入内存中

int i = N; //此时为N分配内存,以后不再分配

int I = M; //预编译期间进行宏替换,分配内存

int j = N; //没有内存分配

int J = M; //再进行宏替换,又一次分配内存

所以尽量用const只读变量吗?

3.const修饰指针时,可以像编译器解析一样,先忽略类型名,然后再看const离谁近就修饰谁。

eg:

const int *p;//忽略int,const修饰*p,p为指针,*p为指针指向的对象,不可变。

Int * const p;//忽略int,const修饰p,p不可变,p指向的对象可变。

       4.void *可以指向任何类型的指针,任何类型的指针都可以直接赋值给它,但void *不能直接赋值给其它类型的指针,必须经过强制类型转换。

       eg:

void * p1;//定义指针时要初始化NULL

int * p2;

p1 = p2;//没有问题,可以把任何类型指针赋值给空指针

p2 = p1;//出错,没有强制类型转换时不能把空指针直接赋值给其它类型指针

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

       eg:

char * Func(void)

{

    char str[6];

    int i=0;

    for(i;i<5;i++)

    {

        str = i+1+0x30;

    }

    str[5]=0;

    printf("%s\n",str);//输出12345

    return str;//str属于局部变量,位于栈内存中,在func函数结束时被释放,所以返回str将有问题。

}

 

3.jpg

在主函数中调用printf("%s",Func());输出结果如下所示:

 

4.jpg

7.平时我们要求函数的参数尽量不多于4个,参数太多了,效率会降低(与具体的CPU有关,ARM就对超过4个参数的处理有讲究)。参数太多,可以考虑使用结构体。

8.volatile修饰的变量,表示编译器对访问该变量的代码不再进行优化。定义一个变量,如果用该变量去初始化其他变量,在初始化语句中,只要该变量不作为左值,则编译器会优化该代码,不会生成汇编代码重新从内存中取该变量的值。相当于只取一次,可以用多次,提高效率。如果使用volatile修饰,告诉编译器不用优化该代码,每次都到内存中取值。

    Eg:

int i = 10;          volatile int i = 10;

int j = i;           int j = i;

int k = i;          int k = i;

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
9
关闭 站长推荐上一条 /3 下一条