C语言学习(六)指针2 数组与指针

数组与指针

1.定义指向数组元素的指针变量:

inta[10];

int* p;

p= &a[0];

a[0]元素的地址赋给指针变量p。也就是使p指向a数组的第0个元素。


C语言规定,数组名代表该数组中首元素的地址。因此,下面两个语句等价:

p= &a[0];

p= a;


在定义指针变量时可以对它赋予初值:例:

int* p = &a[0];

它等效于下面两句:

int* p;

p= &a[0];


也可以在定义时写成:

int* p = a; (a数组首元素阿地址赋值给指针变量p)



2. C语言规定: 如果指针变量已指向数组中的一个元素,则指针变量+1指向同一数组中的下一个元素,而不是将p的值(地址)简单的+1例如:

voidmain() {

inta[] = {1,2,3,4,5,6};

int* p1 = a;

printf("%d\n", *p1);

p1= p1 + 1; /*也可以写成:p1= a + 1;*/

printf("%d\n",*p1);

}

输出:1 2


如果p1的初值为&a[0],则:

a)p1 + i或者a+ i,就是a[i]的地址。

b)*(p+i)*(a+i)表示p+ia+i所指向的数组元素,即a[i]


3.引用一个数组元素:

a)下标法,如a[i]形式

b)指针法,如*(a+i)*(p+i)。其中a是数组名,p是指向数组元素的指针变量。


4.3中方法输出数组中的全部元素。

a)for循环


b) *(p+i)方式

voidmain() {

int*p,i;

inta[] = {0,1,2,3,4,5,6,7,8,9};

p= &a[0];

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

printf("%d",*(p+i));

}

}


c)* p方式

voidmain() {

int*p,i;

inta[] = {0,1,2,3,4,5,6,7,8,9};

for(p= a; p < (a+10); p++) {

printf("%d",*p);

}

}


5.使用指针变量指向数组元素时,需要注意:


a)可以通过改变指针变量的值指向不同的元素。例如,上面3种遍历数组方法中的第三种c)* p方式就是用指针变量p来指向元素,用p++使p的值不断改变从而指向不同的元素。如果不用p而使数组名a变化是不行的。例如:

for(p= a; a < (p + 10); a++) {

printf(“%d”,*a);

}

因为数组名a代表数组首元素的地址,是一个指针常量,它的值在程序运行期间是不变的。因此a++无法实现。

b)要注意指针变量的当前值。


c)在定义数组时,虽然指定了数组的长度,但是实际上指针变量可以指向数组长度后面的元素,例如:

voidmain() {

int*p,i;

inta[] = {0,1,2,3,4,5,6,7,8,9};

p= a;

printf("%d",*(p + 10)); /*指向数组的第11个元素,但是a数组只有10个元素*/

}

编译运行并不出错,输出:-1076023500


应该避免出现这样的情况。在使用指针变量指向数组元素时,应该保证指针指向数组中有效的元素。


d)注意指针变量的运算。 如果p指向数组a的首元素(p= a),则:

1)p++ (p+=1).使p指向下一个元素,即a[1]。若再执行*p,则得到下一个元素a[1]的值。


2)* p ++,由于++*同优先级,所以结合方向自右而左,因此它等价于*(p++)。作用是先输出*p的值,然后再p+1,例如:

voidmain() {

int*p,i;

inta[] = {0,1,2,3,4,5,6,7,8,9};

p= a;

printf("%d",*p++);

}


输出:0


voidmain() {

int*p,i;

inta[] = {0,1,2,3,4,5,6,7,8,9};

p= a;

printf("%d",*++p);

}


输出:1

3)*p++*++p作用不同。前者是先取得*p的值,再加1,后者是先加1,再取得*p的值。如果p初值为a(即p=&a[0]),则*p++a[0],*++pa[1]



6.当用数组名作为参数时,如果形参数组中各元素的值发生变化,实参数组元素的值也会改变。


7.实参数组名代表该数组的首元素。而形参用来接受从实参传递过来的首元素地址。因此,形参一个是一个指针变量(只有指针变量才能存放地址)。实际上C编译都是将形参数组名作为指针变量来处理的。例如:

swap(intarr[],int n)


在编译时将arr作为指针变量处理,相当于:


swap(int* arr,int n)


8.多维数组与指针

a)多维数组元素的地址

int a[][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

从二维数组的角度看,a代表二维数组首元素的地址,现在首元素是一个由4个整形元素的组成的一维数组,因此a代表的是第0行的首地址。a+1代表第1行首地址,a+1的含义是a[1]的地址。

a[0],a[1],a[2]是一维数组名,在C语言中规定数组名代表数组首元素地址,因此a[0]代表一维数组a[0]中第0列元素的地址,即&a[0][0]a[1]的值是&a[1][0],a[2]的值是&a[2][0]

a[0]为一维数组,应该用a[0]+1来表示01列元素的地址。正如有一个一维数组xx+1是其第一个元素x[1]的地址一样。a[0]+0,a[0]+a分别是a[0][0]a[0][a]元素的地址。

a[0]*(a+0)等价(因为a是一个二维数组,所以*(a+0)内容是一个一维数组的地址),a[1]*(a+1)等价,a[i]*(a+i)等价。因此a[0]+1,和*(a+0)+1都是&a[0][1]a[1][2]*(a+1)+2的值都是&a[1][2]


既然a[0]+1*(a+0)+1a[0][1]的地址,那么*(a[0]+1)就是a[0][1]的值了。同理*(*(a+0)+1)或者*(*a+1)也是a[0][1]的值。

a[i]的性质作进一步说明:a[i]从形式上看是a数组中的第i个元素。

如果a是一维数组名,则a[i]代表a数组序列号为i的元素所占内存的内容。a[i]是有物理地址的,是占内存的。

但是如果a是二维数组名,则a[i]代表一维数组名。它只是一个地址,并不代表某一元素的值(如同一维数组名只是一个指针)。a,a+i,a[i],*(a+i),*(a+i)+j,a[i]+j都是地址。而*(a[i]+j)或者*(*(a+i)+j)是二维数组元素a[i][j]的值。


9.例,输出二维数组有关的值。


#include<stdio.h>


#defineFORMAT "%d,%d \n"

voidmain() {

inta[][3] = {{1,2,3},{4,5,6},{7,8,9}};


printf(FORMAT,a,*a);//0行首地址和00列元素地址


printf(FORMAT,a[0],*(a+0));//00列元素地址


printf(FORMAT,&a[0],&a[0][0]);//0行首地址和00列元素地址


printf(FORMAT,a[1],a+1);//10列元素地址和1行首地址


printf(FORMAT,&a[1][0],*(a+1)+0);//10列元素地址


printf(FORMAT,a[2],*(a+2));//20列元素地址


printf(FORMAT,&a[2],a+2);//2行首地址


printf(FORMAT,a[1][0],*(*(a+1)+0));//10列元素的值

}


输出:

-1076350692,-1076350692

-1076350692,-1076350692

-1076350692,-1076350692

-1076350680,-1076350680

-1076350680,-1076350680

-1076350668,-1076350668

-1076350668,-1076350668

4,4


9.用指针变量输出二维数组元素的值


#include<stdio.h>

void main() {

int a[][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};

int * p;

for(p= a[0]; p < a[0] + 12; p++) {

if((p- a[0]) % 4 == 0) {

printf("\n");

}

printf("%4d",*p);

}

printf("\n");

}


输出:

0 1 2 3

4 5 6 7

8 9 10 11


10.如果要输出某个指定的数值元素(例如a[1][2]),则应事先计算该元素在数组中的相对位置(即相对于数组起始位置的相对位移量)。计算a[i][j]在数组中的相对位置的计算公式为:

i* m + j

其中m为二维元素的列数。例如,3x4的二维数组,它的23列元素a[2][3]a[0][0]的相对位移量为2*4+3=11字节。如果开始时使用指针变量p指向a[0][0],为了得到a[2][3]的值,可以用*(p+2*4+3)表示,(p+11)a[2][3]的地址。a[i][j]的地址为&a[0][0]+i*m+j


例子:输出二维数组任意一行任意一列元素的值。


#include<stdio.h>

void main() {
int a [][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
int num1,num2;
num1 = 1;

num2 = 2;


int (*p)[4];
p = a;
printf("%d\n",*(*(p+num1)+num2));

}


输出:6


程序中有 int(*p)[4]; 表示p是一个指针变量,指向包含4个整形元素的一维数组。

1)int a[4]; a4个元素,每个元素为整形

2)int (*p)[4]; *p4个元素,每个元素是整形。p是指向一维数组的指针。


11.用指向数组的指针作函数参数。用指针变量做形参有两种方法:a)用指向变量的指针变量 b)用指向一维数组的指针变量.


例子:3个学生,4门成绩,计算宗总平均分和第n个学生的成绩。


#include<stdio.h>

voidmain() {

int a [][4] = {{76,76,58,67},{88,79,87,69},{98,78,78,97}};

void average(int * p,int n);

void search(int (*p)[4],int n);

average(a[0],12);

search(a,2);

}

void average(int * p,int n) {

int* p_end;

int sum = 0,aver;

p_end= p + n - 1;

for(;p <= p_end; p++) {

sum= sum + (*p);

}

aver= sum / n;

printf("average= %d \n",aver);

}

voidsearch(int (*p)[4], int n) { // p指向一个具有4个元素的一维数组

int i;

for(i= 0; i < 4; i++) {

printf("%d",*(*(p+n)+i));

}

printf("\n");

}


输出:

average= 79

9878 78 97


例子:在上例基础上,找到一门课程不及格的学生,输出他的全部成绩。


#include<stdio.h>

voidmain() {

int a[][4] = {{76,76,58,67},{88,79,87,69},{98,78,78,97}};

void search(int (*p)[4],int n);

search(a,3);

}

void search(int (*p)[4], int n) {

int i,j,flag;

for(j= 0; j < n; j++) {

flag= 0;

for(i= 0; i < 4; i++) {

if(*(*(p+j)+i)< 60)

flag= 1;

}

if(flag== 1) {

printf("No:%dstudent \n",j+1);

for(i= 0; i < 4; i++) {

printf("%d",*(*(p+j)+i));

}

printf("\n");

}

}

}


输出:

No:1student

7676 58 67


文章链接:http://blog.csdn.net/murongshusheng/article/details/8690295



你可能感兴趣的:(c,数组,C语言,指针)