数组和指针

数组和指针

数组和指针的统一性C语言的长处之一,用指针可以很方便地访问数组和模拟动态分配的数组。

多数的数组引用都会退化为数组第一个元素的指针,这是C语言中数组和指针等价的基础。因此,数组在C语言中是个二等公民:你永远也不能作为一个整体操作数组(例如:复制或将它们传入数组),因为一旦你提到数组的名字,你所得到的就是一个指针而不是一个数组了。

       关于char a[]=”hello”char *p=”world”的区别:

clip_image002[4]

       其中a为数组预留了6个字符的位置,而p只是提供了一个指针。本质区别为:一旦出现类似a的数组和类似p的指针,以后的操作就会按照不同的方法计算。

       数组和指针的区别

数组是一个由(同一类型的)连续元素组成的预先分配的内存块;

指针是一个对任何位置的(特定类型的)数据元素的引用;

数组自动分配空间,但是不能重分配或改变大小;

指针必须被赋值以指向分配的空间(可能使用malloc),但是可以随意重新赋值(即指向不同的对象),同时除了表示一个内存块的基址之外,还有许多用途;

数组和指针的联系

指针可以模拟数组;

几乎没有所谓数组的东西,下标操作符实际上是个指针操作符;

从更高的层次上看,指向一块内存的指针本质上也就是一个数组;

 

如果a是数组int a[10],那么对a的引用就是“int型的指针,而&a“10int的数组的指针

 

       sizeof操作符如果能够判断出数组的大小,就会返回数组的大小,如果数组的大小未知或者数组已经退化为指针,就不能提供数组的大小了。

 

指针

指针

l  指针毫无疑问是C语言中最强大和最流行的功能之一;

l  指针的好处:

n  动态分配数组;

n  对多个相似变量的一般访问;

n  按引用传递函数参数;

n  各种动态分配的数据结构,尤其是数和链表;

n  遍历数组:例如解析字符串;

n  高效地、按引用复制数组和结构,特别是作为函数参数的时候;

l  不能对void*指针进行算术操作的原因是编译器不知道所指对象的大小;

没有什么通用指针类型void *指针只能保存对象(也就是数据)指针。但是,可以确保的是,所有的函数指针类型都可以相互转换,只要在调用之前转回了正确的类型即可。

表达式

表达式

l  函数调用时的参数的求值顺序是不确定的;

l  序列点:一个时间点,此刻尘埃落定,所有的副作用都已经确保结束;

l  在上一个和下一个序列点之间,一个对象所保存的值至多只能被表达式的求值修改一次,而且只有在确定将要保存的值的时候才能访问前一个值;

l  一旦一个表达式或程序未定义,则它的所有方面都会变成未定义;

l  三元操作符?:可以生成一个值,但是不能被复制;

结构、联合和枚举

结构、联合和枚举

l  所谓的抽象数据类型,应该只在源文件中看到细节才完美;

l  对于大工程而言,最好将函数原型和结构声明放在单独的头文件中;

l  在结构中,比较安全的定义方式是使用指针而不是数组;

l  不能使用==!=来比较结构是因为可能会遇到结构中没有使用的洞hole的随机内容而导致失败;

l  当结构作为函数参数传递的时候,通常会把整个结构都推进栈,需要多少空间就使用多少空间,正是为了避免这个代价,程序员经常使用指针而不是结构

l  为了广泛的可移植性,在读写文件的时候,最好使用二进制b选项;

l  正确地对齐是种编译器高效访问的策略;

l  将结构中的域按照从大到小的顺序排列可以最大限度地降低填充的影响;

l  结构为一级对象,而结构为二级对象,不能直接对结构进行赋值等;

l  在原来的ANSI C中,只有联合中的第一个成员可以被初始化,C99引入了指定初始式,可以用来初始化任意成员

l  联合无法跟踪到底是哪一个域在使用;

l  枚举的优点为:自动赋值;调试器在检验枚举变量时,可以显示符号值;它们服从数据块作用域规则。一个缺点是程序员不能控制这些非致命的警告,有些程序员则反感于无法控制枚举变量的大小;

l  位域冒号:指定二进制大小的方法只适用于结构和联合的成员;

位域是可以移植的;

声明和初始化

声明和初始化

l  char至少有8位,short intint至少有16位,long int至少有32位,在C99中,long long至少有64位;

l  C语言中,唯一能够让你以二进制位的方式指定大小的地方就是结构中的位域;

l  尽管一个全局变量或函数可以在多个编译单元中有多处声明declaration,但是定义definiton却最多只能允许出现一次

l  extern只对数据声明有意义,因为函数默认就有该属性;

l  typedef用来定义新的类型名称,而不是定义新的变量或函数;

l  对于typedefdefine而言,最好使用typedef,因为它可以处理指针类型,而define有时不可以,就算可以,也要加很多的括号;

l  定义结构中包含结构本身指针的较好风格:

n  clip_image002

l  C语言有4种作用域:函数、文件、块和原型;

l  C语言有四种命名空间:

n  行标label:即goto的目的地;

n  标签tag:结构、联合和枚举的名称;

n  结构/联合成员;

n  普通标识符:函数、变量、类型定义名称和枚举常量;