数组应用小结(一)
来源:互联网 发布:ai技术 编程语言 编辑:程序博客网 时间:2024/05/22 00:10
数组是类型相同的对象的序列,其中的对象称为数组元素。
数组是C/C++中最常用的数据结构,由于数组名类似于指针,加上C/C++不会对数组边界进行检查,所以在数组运用过程中很容易出错。
下面总结下自己对数组的理解:
1. 数组名是一个"常量地址"(函数名也是),不能作为左值。
(按道理是不能对数组名再“取地址”的,编译系统做了“容错”处理,就是把“取常数地址的地址”与“常数地址”等价成一回事,如把 &hello处理成与 hello等同 , 所以,它们是一样的,编译程序这样做是故意的行为,仅仅是为了“容错”。)
数据名作为函数形参时,其全面沦落为一个普通指针。在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。
为什么字符数组输出数组名为数组内容,而不是地址?
输出字符数组时,就会把首地址转换成char *p的,以字符串的形式输出。
2.数组传值(址)
一维数组,可以直接作为参数传值(同时传数组长度或定义结束标志)。
二位数组,可以转换为指针数组(char c[1][2] 转为 char (*c)[2]),再进行传递。
三维或以上,分解为一维数组(char c[1][2][3] 转换为 char (*(*c))[3]),再进行传递。
数组名做形参时,是传值还是传址?
数组就是一块内存, 数组名就是内存的首地址, 和指针是一样的, 传参传数组, 其实就是传了个指针, 不会复制一份的,
3.数组和指针
数组和指针被编译器按照不同方式处理,产生不同的代码;对于编译器来说,一个数组就是一个地址,而指针是一个地址的地址。
例如p[3]和*(p+3)都得到一样结果,但访问过程不一样,指针其实是多了一步,就是指针必须先去取它的地址的内容;而数组不用,直接加偏移地址取元素就可以了。
4.数组越界,strcpy
C/C++并不会对数组边界进行检查,当对数组赋值大于数组长度时,就会覆盖周边变量的值。
注意:
在使用strcpy时,数组不能作为源参数(const char *src),因为对src的拷贝以'\0'作为终止符,数组没有'\0',就会越界一直往下找,直到找到为至。
char *strcpy(char *dest, const char *src);
5.零长度数组应用
零长度数组不是所有的c标准都支持,gnu c支持,ansi c不支持,c++不支持。
零长度数组(通常是长度为1数组)一般放在结构体的结尾,用于不定长数据的“动态扩展”,所以在给结构体分配内存时必须预先分配足够的内存,保证后面扩展时不会超过预先分配的内存的大小。(结构体的里面的数据在内存中按顺序存储的。)
#include <iostream.h>/*测试数组边界*/void test_array_boundary(){ char array[] = {'a', 'b'}; char *p0 = array;//输出p0包含a,b和之后的随机值 char *p1 = "abcdefgh\0xyz"; //输出p1不包含\0之后的值 char p[1]; for(int i = 0;i<0xffff; i++) {p[i]='a'+i; //程序将在某一时刻Segmentation fault,p[i]踩到了非法内存 cout<<p[i]<<endl;; }} /*测试数组越界,踩内存这个例子里x的值会被str的值覆盖。*/int test_overstep(){int x=35; char str[12]; //str = "abcdefghijk"; //数组名不能作为左值strcpy(str,"abcdefghijkl"); //共13个字母/*for(int i = 0; i<25; i++) //i = 24时 { str[i] = 'a';}*/cout<<x<<endl;cout<<&x<<endl;cout<<str<<endl;cout<<&str<<endl;return 1;}/*0长度数组测试注意,当结构体中只包含零数组时候,求sizeof时值为0*/struct zeroStruct{ int length; //char bytes[1]; char bytes[0];//这里的 bytes 可以作为扩展数组用};void test_zeroStruct(){ int length = 100; zeroStruct *zero_p = (zeroStruct*)malloc(sizeof(zeroStruct)+length); for(int i = 0; i<100; i++) zero_p->bytes[i] = 'a'+i; } /*strcpy应用,输出为随机值strcpy结束标志是'\0',数组是不以'\0'为结束标志,所以这里直到拷贝找到'\0'*/void test_array_strcpy(){ char string[10], str1[10]; for(int i=0; i<10; i++) { str1[i] = 'a'; } strcpy(string, str1 ); cout<<string<<endl; //输出为随机值}int main(){ //test_array_boundary(); test_overstep(); test_zeroStruct(); test_array_strcpy(); return 1;}
- 数组应用小结(一)
- 指针应用小结(一)
- 后缀数组应用小结
- Java 多线程应用小结(一)
- XBMC应用开发小结--(一)
- 数组的应用(一)
- 一维树状数组小结
- 小结 | 一维数组,二维数组
- java 数组的应用(一维)
- 小结(数组、循环)
- 一维数组简易应用
- 数组的简单应用 一
- 一维数组及其应用
- 数组与集合的应用之数组演练(获取一维数组最小值)
- oracle 小结(一)
- VB 小结(一)
- 小结(一)
- 多线程小结(一)
- hdu 5007
- Oracle Connect By用法
- Common lisp 学习之路(2)
- ——Diary6(Java异常)
- hdu 5003 模拟水题
- 数组应用小结(一)
- 设置tr的边框
- java中重载与重写的区别
- mybatis实战教程(mybatis in action),mybatis入门到精通
- hdu 5001 从任意点出发任意走d步不经过某点概率
- SEAndroid安全机制对Android属性访问的保护分析
- js将字符串时间格式yyyy-MM-dd hh:mm:ss 转换为long
- JAVA电子门管理系统
- Steganography