您的位置:首页 > 其它

再谈一维数组、二维数组与指针、数组指针

2016-01-12 19:12 232 查看
首先看如下一下基础:

一、int *p:p是指向一个整数变量的指针(int *p=&i ,p指向整型变量i )

char *p:p是指向一个字符变量的指针

由int data[30]; int *p;有p=data;或p=&datd[1](i=0,1,2,3....)

上面成立的原因:(1)数组名是该数组首元素的地址

(2)&data表示取整个数组的地址,包括多维数组。&data[0]取数组首个元素的地址。单独data则亦表示数 组首元素的地址。

(3)p是p是指向一个整数变量的指针

二、 int a[3][4];a是指向由4个int数据构成的数组的指针

int (*p)[4];p是指向由4个int数据构成的数组的指针

于是必然有:p=a;

分析二成立的原因:1、c primer plus中对二维数组和数组指针的定义即是上面的方式;

2、因为在数组与指针中有p[m]=*(p+m)的关系。直接将上面的数组指针int (*p)[4];改写

成int (*p+0)[4];即等效于int p[0][4];自然可以很清晰的理解了。

三、字符的存储形式:每个字符以整数的形式储存。

字符串的储存方式:一“\0”结尾的char数组。

四、c语言中字符串,就是字符数组,故指针访问字符串即等效于指针访问数组元素。

1)、数组与数组,数组与指针,指针与指针之间的赋值

数组之间是不可以直接赋值的,要直接赋值的话,也只能是利用循环,一个一个的赋值:

#include<stdio.h>
int main()
{
int a[10]={0,1,2,3,4,5,6,7,8,9};
int b[10]={1,2,3,4,5,6,7,8,9,10};
for(int i = 0;i<10;i++)

{
a[i]=b[i]; (可以为*(a+i) = *(b+i) )
}
return 0;
}

当然还可以通过其他方法来实现,比如取地址运算,把数组a的首地址赋给B数组,不过这要通过指针来实现:

#include<stdio.h>
int main()
{
int k;
char *s[]={"you","are","the","one"};
char **q;
for(k=0;k<4;k++)
{
*q[k]=*s[k];
printf("%s\n",*q[k]);
}
}

还有一种简单点的方法就是拷贝运算,你可以利用c语言库里面已经定义好的函数直接实现你所要实现的功能,实现方法如下:

#include <string.h>
#include <stdio.h>
void main()
{
char a[10]={"asdsadsa"},b[10];
strcpy(b,a);
printf("%s\n",b);
}

五、两个指针之间的赋值则就是根据数组间的赋值就可以了,只需利用( a[i] = *(a+i) ,i=0,1,2,3,4.....)

六、指针字符与字符数组之间的关系

采用指针存储字符串,其实质就是把字符串的首地值附给基类型为char的指针变量,从而可以从字符串首元素开始对字符串进行操作,但是,,这里面也存在一点问题,如下:
int main()
{
char *p="hello";
p[0]='M';
printf("%s\n",p);
return 0;
}
运行结果会出现断错误,原因在于,*p="hello" 这句仅仅声明了一个指针变量,指向字符串"hello ",而"hello "这个字符串程序没有给它分配空间,编译器把它分配到常量区.而常量字符串的值是不允许被修改的 ,所以会出现断错误.

程序改为如下就正确了
int main()
{
char p[12]="hello";
char *p1=p;
p1[0]='M';
printf("%s\n",p1);
return 0;
}

因为,p[12]="hello "是你自己定义的一个长度为12 的字符数组,所以字符串"hello world"编译器会给它分配空间(在栈中及非常量区),所以可以修改它的值.

字符串“hello”本身就是一个常量字符指针,而对于指针p,无非就是一个地址的拷贝,也就是“hello”地址的拷贝,相当于p指向一个字符串常量,字符串常量是不予许改变的!
而对于p[]来说就不一样了,虽然hello本身是常量,不过此时拷贝给p[]的不是地址,而是内容,也就是“hello”,也就是p本身拥有一个自己的hello副本,可以对其进行想要的合法操作,比如改变等.

最后说明:
c语言中,不能对字符指针变量指向的字符串再赋值,这不是绝对正确的:当指针指向的字符串是常字符串时当然不能再赋值,因为目标是“常量”,而当指针指向的字符串不是常字符串时就可以再赋值,比如用动态申请内存方法创建的字符串。具体说就是用char *p="abcqer12345";这种方法定义字符串是不能通过指针改变内容的,原因是这个定义确定了abcqer12345是字符串常量——因为char *p="abcqer12345";被编译器解释为“创建一个字符串常量abcqer12345,并把它的首地址(就是a的地址)赋给char *型指针p。
而如果用动态申请内存时基本方式如下:
在C语言中,动态申请内存可以用stdlib.h中声明的malloc函数。

函数原型:

void *malloc(unsigned int num_bytes);

num_bytes为要申请的内存数量。申请成功,则返回指向这块内存的指针;失败则返回NULL。

申请成功之后,就可以使用gets来接收字符串。代码如下:

#include <stdio.h>
#include <stdlib.h>
int main()
{
int size = 100;
char *str;

str = malloc(size);
gets(str);
puts(str);
free(str);

return 0;
}


七、 补充知识:指针

指针在定义后必须要先初始化才能使用,因为未初始化的指针指向哪里,根本就不知道,使用后结果不可预知,如果指向的内存中比较重要的地方,可能会导致系统异常,如提示指向了一个不可用的地址之类。

对指针进行初始化,有三种方法:

运用int *p=0;这个语句老老实实的将指针初始化了;

把int *p=0和p=&i这两句话连成一句话: int *p=&i(&i可以用a,当a表示已定义的数组或已有所指的指针等);这样,就既把指针变量p初始化了,又把它指向了某个值;

用常量来初始化一个指针。则需用强制类型转换,找一个内存地址,即(ElementType *) 来把常量转换成内存中的一个地址。既采用:

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