再来看一下数组(注意不是数组的元素,是数组)作为参数传递的情况
#include stdio.hvoid changeValue(int a[]){ a[0] = 10;}int main(){ int a[2] = {1,2}; changeValue(a); for (int i = 0; i 2; ++i){printf("a[%d]=%dn",i,a[i]); } /*打印结果 a[0]=10 a[1]=2 */}
多维数组
多维数组其实可以看成是一个特殊的一维数组,只是每个元素又是一个一维数组,下面简单看一下多维数组的初始化和赋值
#include stdio.hint main(){ int a[2][3];//2行3列,二维数组可以看成是一个特殊的一维数组,只是它的每一个元素又是一个一维数组 a[0][0] = 1; a[0][1] = 2; a[0][2] = 3; a[1][0] = 4; a[1][1] = 5; a[1][2] = 6; for (int i = 0; i 2; ++i){for (int j = 0; j 3; ++j){ printf("a[%d][%d]=%d,address=%xn", i, j, a[i][j], &a[i][j]);} } /*打印结果 a[0][0]=1,address=f8fb24 a[0][1]=2,address=f8fb28 a[0][2]=3,address=f8fb2c a[1][0]=4,address=f8fb30 a[1][1]=5,address=f8fb34 a[1][2]=6,address=f8fb38 */ //初始化并直接赋值 int b[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; //由于数组的赋值顺序是先从第一行第一列,再第一行第二列...然后第二行第一列...,所以我们也可以写成如下形式 int c[2][3] = { 1, 2, 3, 4, 5, 6 }; //也可以只初始化部分数据,其余元素默认为0 int d[2][3] = { 1, 2, 3, 4 }; for (int i = 0; i 2; ++i){for (int j = 0; j 3; ++j){ printf("d[%d][%d]=%dn", i, j, d[i][j]);} } /*打印结果 d[0][0]=1 d[0][1]=2 d[0][2]=3 d[1][0]=4 d[1][1]=0 d[1][2]=0 */ //当然下面赋值也可以 int e[2][3] = { {}, { 4, 5, 6 } }; //可以省略行号,但是绝对不可以省略列号,因为按照上面说的赋值顺序,它无法判断有多少行 int f[][3] = { {1,2,3},{4,5,6} };}
扩展--多维数组的存储
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)以上面a数组为例,它在内存中的结构如下图
根据上图和一维数组的存储,对于二维数组可以得出如下结论:数组名就是整个二维数组的地址,也等于第一行数组名的地址,还等于第一个元素的地址;第二行数组名等于第二行第一个元素的地址。用表达式表示:
a=a[0]=&a[0][0] a[1]=&a[1][0]
关于多维数组,其实可以以此类推,在此不再赘述。
字符串
在C语言中是没有字符串类型的,如果要表示字符串需要使用char类型的数组,因为字符串本身就是多个字符的组合。但是需要注意的是字符串是一个特殊的数组,在它的结束位置必须要加一个” ”(ASCII中0是空操作符,表示什么也不做)来表示字符串结束,否则编译器是不知道什么时候字符串已经结束的。当直接使用字符串赋值的时候程序会自动加上” ”作为结束符。
//// main.c// ArrayAndString//// Created by KenshinCui on 14-7-06.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#include stdio.hint main(int argc, const char * argv[]){ char a[] = {'K','e','n','s','h','i','n',' '}; printf("%s",a); //结果:Kenshin,注意使用%s输出字符串内容,如果换成整形输出格式其实输出的是a的地址 printf("n"); printf("address=%x", a); //结果:address=5fbff890 printf("n"); //后面的 绝对不能省略,如果没有 则会出现如下情况 char b[] = { 'I', 'a', 'm'}; printf("%s",b); //没有按照期望输出,多了一些垃圾数据,在当前环境打印结果:IamKenshin printf("n"); printf("address=%x",b); //结果:address=5fbff88d printf("n"); //直接赋值为字符串,此时不需要手动添加 ,编译器会自动添加 char c[] = "Kenshin"; printf("c=%s",c); //结果:c=Kenshin printf("n");//二维数组存储多个字符串 char d[2][3]={"Kenshin","Kaoru","Rose","Jack","Tom","Jerry"}; return 0;}
从上面代码注释中可以看到打印b的时候不是直接打印出来“Iam”而是打印出了“IamKenshin”,原因就是编译器无法判断字符串是否结束,要解释为什么打印出“IamKenshin”我们需要了解a和b在内存中的存储。
从图中我们不难发现由于a占用8个字节,而定义完a后直接定义了b,此时分配的空间连续,b占用3个字节,这样当输出b的时候由于输出完“Iam”之后并未遇到” ”标记,程序继续输出直到遇到数组a中的“ ”才结束,因此输出内容为“IamKenshin”。
扩展--字符串操作常用函数
下面简单看一下和字符和字符串相关的常用的几个函数
//// main.c// ArrayAndString//// Created by Kenshin Cui on 14-7-04.// Copyright (c) 2014年 Kenshin Cui. All rights reserved.//#include stdio.hint main(int argc, const char * argv[]){ /*字符操作*/ putchar('a'); //结果:a,putchar一次只能输出一个字符 printf("n"); putchar(97);//结果:a printf("n"); char a; a=getchar();//getchar()一次只能接收一个字符,可以接收空格、tab、回车 printf("a=%c",a); printf("n"); /*字符串操作*/ char b[]="Kenshin"; printf("b=%s",b); printf("n"); puts(b); //puts用于输出单个字符串,不能像printf格式化输出,会自动添加换行 printf("n");char c[10]; scanf("%s",c);//注意c没必要写成&c,因为c本身就代表了数组的地址 printf("c=%sn",c);//注意即使你输入的内容大于10,也能正确输出,但是下面的gets()函数却不行 printf("n");//gets()函数,注意它是不安全的,因为接收的时候不知道它的大小容易造成溢出,建议不要使用 char d[10]; gets(d); //gets一次只能接收一个字符串,但是scanf可接收多个;scanf不能接收空格、tab,gets则可以 printf("d=%s",d); printf("n");char e[]={'K','s',' '}; printf("%lu",strlen(e)); //结果是:2,不是3,因为 不计入长度 printf("n"); char f[]={"Kenshin"}; printf("%lu",strlen(f)); //结果是:7 printf("n");char g[5]; strcpy(g,"hello,world!"); printf("%s",g); //结果是:hello,即使定义的g长度为5,但是也能完全拷贝进去 printf("n"); char h[5]; char i[]={'a','b','c',' ','d','e','f',' '}; strcpy(h,i); printf("%s",h); //结果是:abc,遇到第一个 则结束 printf("n");strcat(i,"ghi"); printf("%s",i); //结果是:abcghi,注意不是abcdefghi,strcat,从i第一 开始使用“ghi”覆盖,覆盖完之后加上一个 ,在内存中目前应该是:{'a','b','c','g','h','i',' ','f',' '} printf("n");char j[]="abc"; char k[]="aBc"; char l[]="acb"; char m[]={'a',' '}; printf("%d,%d,%d",strcmp(j,k),strcmp(k,l),strcmp(l,m));//遇到第一个不相同的字符或 则返回两者前后之差,结果:32,-33,99 printf("n"); return 0;}
注意在Xcode中会提示gets是不安全的,因为Xcode使用的是gcc编译器,在gcc编译器中已经不能正确编译gets()函数,推荐使用fgets()。