C语言学习笔记与总结(一)
2014-05-04 21:37
375 查看
一、数据定义
用变量a给出下面的定义a) 一个整型数(An integer)
b)一个指向整型数的指针( A pointer to an integer) <
4000
br />
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
限定词volatile告诉编译器该变量除了可被程序改变外还可被其他代理改变。语法同const。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
几个典型的例子:
?; 并行设备的硬件寄存器(如:状态寄存器)
?; 一个中断服务子程序中会访问到的非自动变量(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
它只可用于指针,并标明指针式访问一个数据对象的唯一且初始的方式。通过允许编译器优化某几种代码增强了计算机的支持。int ar[10];
int * restrict restar =(int *)malloc(10 * sizeof(int));//指针restar是访问malloc()分配内存的唯一且初始的方式
int * par =ar;
for(int n = 0;n<10;n++)
{
par
+=5;
restar
+= 5;
ar
*=2;
par
+=3;
restar
+=3;
}
知道了restar是访问它所指向的数据块的唯一初始方式,编译器就可以用具有同样效果的一条语句来代替包含restar的两个语句:
restar
+=8 //可以进行替换
然而par泽不会精简。
restrict使编译器可以放心的寻找计算的捷径。
更加典型的利用时C库中的两个函数。在C99标准下,他们的原型如下:
void * memcpy(void * restrict s1,const void *restrict s2,size_t n)
void * memmove(void * s1,const void * s2,size_t n)
其中,memcpy()要求两个位置不重叠,memmove()没有这个要求。restrict使得s1和s2不能访问同一数据块。
相关文章推荐
- 黑马程序员-IOS学习笔记-C语言基础其他数据类型及总结
- C语言学习笔记总结
- [黑马程序员]09[C语言]循环控制语句部分学习笔记总结
- 【C语言学习笔记】qsort函数总结
- C语言学习笔记 (007) - 数组指针和通过指针引用数组元素的方法总结
- C语言学习笔记 (008) - C语言字符串操作总结大全(超详细)(转)
- Flask学习总结笔记(7) -- 程序文件组织结构
- Python学习笔记——一些常用函数、常见错误总结
- C语言学习笔记--动态库和静态库的使用
- 学习笔记的总结和回顾(2017.2.14)
- Coursera吴恩达机器学习课程 总结笔记及作业代码——第4周神经网络
- c语言学习第一天笔记
- 【学习总结】Python基础知识笔记2
- SEO学习笔记-误区和经验总结
- PHP 开发 APP 接口 学习笔记与总结 - APP 接口实例 [6] 版本升级接口开发
- Bootstrap学习总结笔记(19)-- 基本插件之Popover提示框
- C语言学习笔记--基础语法一
- PyCharm学习笔记及Python基础语法总结
- 【C语言学习笔记】初识GCC编译器
- vue.js学习笔记(三)--父子组件通信总结