一、数据定义
用变量a给出下面的定义
a) 一个整型数(An integer)
b)一个指向整型数的指针( A pointer to an integer)
c)一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an intege)r
d)一个有10个整型数的数组( An array of 10 integers)
e) 一个有10个指针的数组,该指针是指向一个整型数的。(An array of 10 pointers to integers)
f) 一个指向有10个整型数数组的指针( A pointer to an array of 10 integers)
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )
答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
等价于int *(a[10]);
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*max_function)(int a); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
二、一些特殊关键字的作用
static
关键字static有三个明显的作用:
a)一旦声明为静态变量,在编译时刻开始永远存在,不受作用域范围约束,但是如果是局部静态变量,则此静态变量只能在局部作用域内使用,超出范围不能使用,但是它确实还占用内存,还存在.
b) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
c) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
const
1)只读。
2)通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
3)使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。
其次它的使用方法,我们先通过一个例子来了解一下:
下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
/******/
前两个的作用是一样,a是一个常整型数。
第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。
第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。
最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。
最后总结一下对全局数据使用const的两种策略(const防止了程序的任意部分的可以错误修改程序的发生):
a)遵循外部变量的惯用规则,在一个文件中定义声明,在其他文件中尽兴引用声明(使用关键里extern)
b)将常量放在一个include文件中。这是还必须使用静态外部存储类(加关键字static)
小细节:在与ANSI兼容的编译器中,下面的代码将产生一个错误信息:
const int nochange;
nochange=12;
然而,可以初始化一个const变量。因此,下面代码是对的:
const int nochange = 12;
上面的声明使nochange成为一个只读变量。在初始化后就不能改变它。
volatile
精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
?; 并行设备的硬件寄存器(如:状态寄存器)
?; 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
?; 多线程应用中被几个任务共享的变量
一个面试题:
?; 一个参数既可以是const还可以是volatile吗?解释为什么。
?; 一个指针可以是volatile 吗?解释为什么。
?; 下面的函数有什么错误:int square(volatile int *ptr){return *ptr * *ptr;}
下面是答案:
?; 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
?; 是的。尽管这并不很常见。一个例子是当一个中断服务子程序修改一个指向一个buffer的指针时。
?; 这段代码有点变态。这段代码的目的是用来返回指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
restrict