关于sizeof表达式作为数组元素个数的编译
想总结这方面的内容,是出于周一参加某公司的笔试题,有一道题是说定义一个整型数组,里面数组元素的个数是用sizeof(unsigned long)表示,这样是否合法?当时写的答案是不合法,因为平时写涉及到申请、定义数组的时候,如果数组大小是一个变量,C++会给报错。而在几天之后我在CB上运行之后,发现并没有错。就查了一下sizeof的用法,看到MSDN上的关于sizeof和常量的解释,说的是sizeof之后得出来的是常量,这应该就是解释了为什么可以用sizeof()来定义一个数组的大小了吧。(后面接着有更合理的解释)
接着看《C陷阱与缺陷》第三章中的指针与数组,之前也有看到别人总结的“指针数组与数组指针”,便试着自己来把所看到的知识总结下。
1.C语言中只有一维数组,且数组大小必须在编译期作为一个常数确定下来。
关于这一点,查了“sizeof 编译期”,出来结果中找到了需要的内容,是一本名叫《Let's C!!!》的书,“sizeof不是函数,默认是一个编译期的运算符,表达式在编译期就能得出”(后面还说明了为什么sizeof(指针)在32位系统上得出的结果都是4字节,因为指针的值是可变的,在运行期可以修改,因此在编译期不能确定指针指向空间的大小)。
还有一个很棒的结果,《C++元编程》 第二节编译期判断继承关系 第3点,C++编译期三大神器(模板偏特化、函数重载、sizeof)着重看了sizeof的用法,在编译期直接对它求长的表达式做类型推导,即只是计算类型的字节把它写入编译出来的代码中,而不管里面的内容是什么。博主举了个例子如下:
#include <iostream> using namespace std; int main(){ int i = 0; cout << sizeof(++i) << endl; cout << i << endl; return 0; }
输出结果是4 0,sizeof确实只是对里面的表达式做类型字节的计算,而并不会运行表达式。
2.对于一个数组,能做的两件事:确定数组大小,获得数组下标为0的元素的指针。
对于数组名传递的形参,实质都是数组首元素指针的传递。
当把数组名用于sizeof的操作数时(此时数组名代表数组,而不是指针),得到的是整个数组所有元素所占的字节总数,即元素个数×类型字节数。
如果数组名用于其它场合,都是将其视为指针。
3.数组指针
写全该名称,就是“指向数组的指针”
int a[12][31]; a是一个有着12个数组类型元素的数组
int (*p)[31]; (*p)是一个拥有31个整型元素的数组,p是指向这个数组的指针。
p = a; p指向数组a的第一个元素,即有着31个元素的数组类型元素的一个。
int a[12][31]; int (*P)[31]; //p数组指针,指向a for (p = a; p < &a[12]; p++){ int *q; for (q = *p; q < &(*p)[31]; q++){ *q = 0; } }
4.指针数组
数组指针和指针数组很容易混淆,关键是语句的读取顺序,从数组名字开始由内向外阅读就比较好区分。
int *p[31]; //p和[31]结合,是一个数组,数组元素的类型是(int *)。也就是说p是一个数组,里面元素是指向整型的指针。
int (*p)[31]; //p和*结合,是一个指针,该指针指向一个有31个整型元素的数组。