您的位置:首页 > 编程语言 > C语言/C++

C语言之数组专题:数组指针、指针数组、数组做函数参数退化、数组名、数组类型

2015-09-13 19:36 549 查看
转自:http://blog.csdn.net/wu5215080/article/details/38989381






1、数组初始化:

数组元素的个数可以显示或隐式指定

int main()

{

int a[10] = {1,2};//其他没初始化元素,编译器默认帮你初始化为0

int b[] = {1, 2};//编译器隐式指定长度为两个元素

int c[20] = {0};

for (i=0; i<10; i++)

{

printf("%d ", a[i]);

}

memset(a, 0, sizeof(a));

getchar();

}

2、数组名理解难点

int a[10]={1,2};

printf("&a:%d,a:%d\n",&a,a);

printf("&a+1:%d,a+1:%d\n",
&a+1, a+1);
数组首元素地址与数组地址:数组名a代表元素首地址,&a代表数组地址。

数组首元素地址=数组地址即:a=&a

&a+1代表的是加一个数组长度sizeof(a),a+1代表的是加一个数组元素长度sizeof(a[0])

一维数组名是一个指针常量

二维数组名是一个数组指针,多维数组名也是一个数组指针,是指向一个低维数组的指针

char array[10][30];

(array+i) //相当于第i行的首地址 //二级指针

(*(array+i)) //一维数组的首地址 //一级指针

*(array+i)+j //相当于第i行第j列的地址 &array[i][j]

*(*(array+i)+j) //相当于第i行第j列的地址 array[i][j]
6、多维数组在物理内存中是线性存储的,只是编译器帮我们优化了



2、初学者数组类型三大难题

数组类型

数组指针:数组是一个指针,该指针是指向一个数组的指针(数组类型和数组指针的关系)

指针数组:指针是数组元素,也就是数组元素中存储的都是指针


1、 数组类型

C语言中的数组有自己特定的类型,数组的类型由元素类型和数组大小共同决定

1、定义一个数组类型:用数组定义变量

void main12()

{

int i = 0;

//定义一个数组类型

typedef int MyArrayType[5]; //int

MyArrayType myArray; //int myArray[5];

for (i=0; i<5; i++)

{

myArray[i] = i +1;

}

for (i=0; i<5; i++)

{

printf("%d \n", myArray[i]);

}

system("pause");

}
2、定义一个数组类型,用数组顶一个数组类型的指针

void main13()

{

int i = 0;

typedef int MyArrayType[5]; //定义一个数组类型

MyArrayType *pArray = NULL; //定义了一个数组类型的指针

Int a[5]={0};

pArray = &a;

for (i=0; i<5; i++) //我通过数组指针的方式来操作a[5]这块内存

{

(*pArray)[i] = i+1; //a[i] = i+1;

}

for (i=0; i<5; i++)

{

printf("%d \n", (*pArray)[i]);

}

system("pause");

}


2、 数组指针

定义数组指针

int i = 0;

//这个是定义了一个类型,这个类型是数组类型

typedef int MyArrayType[5]; //int

//这个是定义了一个类型,定义了一个指针类型,定义了一个指向数组的指针类型。。。。

typedef int (*MyPArrType)[5] ; //数组指针

MyPArrType myPoint; //

int b[5];

myPoint = &b; //变量取地址给指针赋值

for (i=0; i<5; i++)

{

(*myPoint)[i] = i+1;

}

for (i=0; i<5; i++)

{

printf("%d ", (*myPoint)[i]);

}

system("pause");

}
1):typedef
int MyArrayType[5]; //定义一个数组类型

MyArrayType *pArray = NULL; //定义了一个数组类型的指针

//这个是定义了一个类型,定义了一个指针类型,定义了一个指向数组的指针类型

2):typedef
int (*MyPArrType)[5] ; //数组指针

MyPArrType myPoint; //int b[5];

3):int
(*myArrayPoint)[5] ; //告诉编译给我开辟四个字节内存

5、指针数组

1、指针数组与数组指针容易混淆

Char *p1[] = {“123”,”456”,”789”};

[]优先级高,先与p结合成为一个数组,再由char*说明这是一个字符型指针数组

//这是一个指针数组、数组3*4、三个一维数组的首地址存放在以指针作为元素的数组中

Char (*p2)[] = {“123”,”456”,”789”};

//编译器只分配4个字节,是一个指针,编译不通过、错误的方式
2、指针数组做函数参数退化

int printfArray(char *buf [30]);

int printfArray(char *buf[]);

int printfArray(char **buf);
指针数组的两种用途

菜单

命令行

指针数组自我结束的三种方法

char* c_keyword[] = { "while", "case","static","do",'\0'};

char* c_keyword[] = {"while", "case","static","do",0};

char* c_keyword[] = {"while", "case","static","do",NULL};

6、当多维数组当做函数参数的话的时候会退化为指针

退化原因的本质是因为程序员眼中的二维内存,在物理内存上是线性存储

//总结:函数调用的时候,把数组首地址和有效数据长度传给被调用函数才是最正确的做法
一维数组做函数参数退化过程

//int a[10] -=-->int a[] ---->int *a

//数组做函数形参的时候,如果在形参中定义int
a[10]语句,

//c/c++编译器会做优化,技术推演如下

//int a[10] -=-->int a[] ---->int *a

一维数组做函数参数退化过程

char buf[10][30])—》char
buf[][30])----》char (*buf)[30])

int printfArray(char buf[10][30]);

int printfArray(char buf[][30]);

int printfArray(char (*buf)[30]);

这三者效果是一样的,也就验证了数组做函数参数退化为指针
第一种做法

int printfArray(int a[])

{

int i = 0;

printf("排序之前\n
");

for (i=0; i<10; i++)

{

printf("%d ", a[i]);

}

return 0;

}
第二种写法
int printfArray04(int *a, int num)

{

int i = 0;

printf("排序之前\n
");

for (i=0; i<num; i++)

{

printf("%d ", a[i]);

}

return 0;

}
1、 C语言中只会以机械式的值拷贝的方式传递参数(实参把值传给形参)
int fun(char a[20], size_t b)

{

printf("%d\t%d",b,sizeof(a));

}
原因1:高效
原因2:

C语言处理a
的时候,它没有办法知道n是几,它只知道&a[0]是多少,它的值作为参数传递进去了

虽然c语言可以做到直接int
fun(char a[20]),然后函数能得到20这个数字,但是,C没有这么做。
2、二维数组参数同样存在退化的问题
二维数组可以看做是一维数组

二维数组中的每个元素是一维数组

二维数组参数中第一维的参数可以省略

void f(int a[5]) ====》void
f(int a[]); ===》 void f(int* a);

void g(int a[3][3])====》 void
g(int a[][3]); ====》 void g(int (*a)[3]);
3、等价关系
数组参数 等效的指针参数

一维数组 char a[30] 指针 char*

指针数组 char *a[30] 指针的指针 char
**a

二维数组 char a[10][30] 数组的指针 char(*a)[30]


7、数组操作基础以及中括号本质

//c语言里面没有字符串这种类型。通过字符数组来模拟字符串

//C风格字符串是以零结尾的字符串

//操作数组的方法:下标法和指针法

void main()

{

int i = 0;

char *p = NULL;

//通过字符串初始化字符数组并且追加\0

char buf4[] = "abcd";

for (i=0; i<strlen(buf4); i++)

{

printf("%c", buf4[i]); //p[]

}

//[] *的本质到底是什么?

//*p 是我们程序员手工的(显示)去利用间接赋值

//[] 只不过是,c/c++编译器帮我们做了一个*p的操作。。。。。。

// buf4[i]======> buf4[0+i] ====> *(buf4+i)

//===*(buf4+i) --> bu4[i];

printf("\n");

p = buf4;

for (i=0; i<strlen(buf4); i++)

{

printf("%c", *(p+i)); //*p

}

system("pause");

}
void main12()

{

//字符数组初始化

//指定长度如果定义的长度剩余部分补充0

char buf1[100] = {'a', 'b', 'c'};

//不指定长度

char buf2[] = {'a', 'b', 'c'};

char buf3[] = {'a', 'b', 'c','\0'};

//通过字符串初始化字符数组并且追加\0

char buf4[] = "abcd";

printf("%s\n", buf4 );

printf("sizeof(buf4): %d\n ", sizeof(buf4));

//注意sizeof是对数据类型进行大小测量也就是数组类型包括了\0

printf("strlen(buf4): %d \n", strlen(buf4));//strlen是求字符串的长度不包括\0

system("pause");

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: