再谈一维数组、二维数组与指针、数组指针
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函数。
函数原型:
num_bytes为要申请的内存数量。申请成功,则返回指向这块内存的指针;失败则返回NULL。
申请成功之后,就可以使用gets来接收字符串。代码如下:
七、 补充知识:指针
指针在定义后必须要先初始化才能使用,因为未初始化的指针指向哪里,根本就不知道,使用后结果不可预知,如果指向的内存中比较重要的地方,可能会导致系统异常,如提示指向了一个不可用的地址之类。
对指针进行初始化,有三种方法:
运用int *p=0;这个语句老老实实的将指针初始化了;
把int *p=0和p=&i这两句话连成一句话: int *p=&i(&i可以用a,当a表示已定义的数组或已有所指的指针等);这样,就既把指针变量p初始化了,又把它指向了某个值;
用常量来初始化一个指针。则需用强制类型转换,找一个内存地址,即(ElementType *) 来把常量转换成内存中的一个地址。既采用:
一、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 *) 来把常量转换成内存中的一个地址。既采用:
相关文章推荐
- oracle 数据仓库
- Log4j使用教程
- 【算法】Canny边缘检测
- NLP/ML/SML/DM etc. website
- 删除线
- bzoj1854(二分图匹配)
- rtems stm32f4
- Picasso 加载图片到RelativeLayout之解决方案
- mbed 按键长短按 实现
- 开源ETL工具kettle系列之常见问题
- Canvas类绘制几何图形
- Delphi调用MSSQL存储过程返回的多个数据集的方法
- 解决ln -s 软链接产生Too many levels of symbolic links错误
- 2015年总结
- atom编辑器社区插件推荐
- PHP:POST接口,插入POST数据到mysql数据库
- JAVA_日期处理
- Hadoop基础 hadoop fs 命令
- 网页抓取jsoup
- 解决错误error: RPC failed; result=56, HTTP code = 200