char a[]和char *a的比较,数组名,数组首地址,a,a,a[0]

char a[]和char *a的比较

指针和数组存在着一些本质的区别。当然,在某种情况下,比如数组作为函数的参数进行传递时,由于该数组自动退化为同类型的指针,所以在函数内部,作为函数参数传递进来的指针与数组确实具有一定的一致性,但这只是一种比较特殊的情况而已,在本质上,两者是有区别的。请看以下的例子:

 

char a[] = "1234567";

char *p = "1234567";

上述两个变量的内存布局分别如下:

 

数组a需要在内存中占用8个字节的空间,这段内存区通过名字a来标志。指针p则需要4个字节的空间来存放地址,这4个字节用名字p来标志。其中存放的地址几乎可以指向任何地方,也可以哪里都不指,即空指针。目前这个p指向某地连续的8个字节,即字符串"1234567"。

 

另外,例 如:对于a[2]和p[2],二者都返回字符‘i’,但是编译器产生的执行代码却不一样。对于a[2],执行代码是从a的位置开始,向后移动2两个字节,然后取出其中的字符。对于p[2],执行代码是从p的位置取出一个地址,在其上加2,然后取出对应内存中的字符。

 

p指针变量本身在栈上,指向的内容在静态存储区;

 

a只是个数组名,本身不占运行时程序的空间,只是在源程序中用来标记一个字符数组(即其首地址),而数组也是存储在栈上的。

 

 

char s1[] = "a";

 

char *s2 = "b";

 

a是在运行时刻赋值的;

 

而b是在编译时就确定的;

 

但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。

 

比如:

 

int main()

 

{

 

char a = 1;

 

char c[] = "1234567890";

 

char *p ="1234567890";

 

a = c[1];

 

a = p[1];

 

 

return 0;

 

}

 

对应的汇编代码

 

10: a = c[1];

 

00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]

 

0040106A 88 4D FC mov byte ptr [ebp-4],cl

 

11: a = p[1];

 

0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]

 

00401070 8A 42 01 mov al,byte ptr [edx+1]

 

00401073 88 45 FC mov byte ptr [ebp-4],al

 

第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。

 

#include<stdio.h>
#include<stdlib.h>
char *function1()
{
     char *a="cdefgh";//在靜態存儲區分配,一直到程序結束
     return a;
}

char *function2()
{
     char a[]="cdefgh";//在棧中分配,函數結束時釋放
     return a;
}
char a[]="cdefgh";
/*這個是常量字串的拷貝,
相當於strcpy(a,"cdefgh"),
這樣寫都會有字串拷貝,
造成時間和空間上的開銷,
如果字串很長儘量不要這樣寫,
由於字元陣列a在棧上,
所以在函數結束後它便無效了..
---------------
char *a="cdefgh";
a直接指向常量字串,
這個字串保存在靜態存儲區中...
所以在函數結束後,它返回的位址仍然有效..
*/
int  main()
{
    char test[]="123";
    test[0]='a';//可以修改數組內部元素的值
    char* test1="456";
    *test1='7';//test1不可以修改,是const char*的類型的值
    /*char *a="cdefgh";
    此時a為const char*,
    也就是說你不能改變*a的值。
    char a[]="cdefgh";你可以通過a[i]改變它的值。*/
    char *i=NULL ;
    char *j=NULL;
    i= function1();//結吉確定
    j= function2();//結果不確定
    printf("/n%s/n",i);
    printf("/n%s/n",j);
    system("pause");
   
}
/*(1)function1()的a和function2()的a都是自動變數,都在棧上分配空間
(2)function1()的a分配的空間=sizeof(char *)=sizeof(void *),
   任何指標的大小都是相同的,指向靜態資料區存的"cdefgh"
(3)function2()的a分配的空間=strlen("cdefgh")+1,並且用來保存"cdefgh"
(4)返回的指標,function1指向靜態資料區,function1指向棧(已自動釋放)
   故function1的值是對的
*/

 

 

=============================================================

 

(1)指针数组: 是数组,但数组中的每个元素都是指针
int *p[5];//如p[2]是指针,可*p[ 2]=3;
(2)指向数组的指针: 是个指针,但它指向的是一个数组
int a[5];
int (*p)[5];//与前一行比较,*p相当于a,即p=&a;就像:int m;int *pm;//*pm就相当于m.pm=&m;
p= &a;//可与前一行合并为int (*p)[5]=&a;
----------------------
a代表这个数组,它是一个指针,指向第一个元素
这里一定要记住,a是数组名,&a代表的不是取a这个变量的地址,而是取数组元素的地址
---------------------------------------
a     的类型是 int[5]       数组
&a    的类型是 int(*)[5]    指针——指向int[5]数组的指针
&a[0] 的类型是 int *         指针——指向int类型的指针。

sizeof(a)=20;
sizeof(*a)=4 =sizeof(a[0]);
sizeof(*&a)=20;//因为p=&a,所以=sizeof(*p),而*p=a,所以=sizeof(a)=20;
---------------------------------------
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));//输出:2,5

指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同,指针只是一个内存地址,但指针指向地址的长度可能不同,如char *pc与int *pi,sizeof(pc)=sizeof(pi)=4,但为什么输出时,cout<<*pc只从内存处取一个字符,而cout<<*pi则从内存处取4个字符,这是由指针类型(char,int)决定的.对A* p;p+1=(A*)(p的地址值+sizeof(A)),如pc+1=pc+sizeof(char)=(char*)(pc的地址值+1个字节),而pi+1=pc+sizeof(int)=(int*)(pi的地址值+4个字节).

对代码中的&a+1,&a是数组指针,其类型为int (*)[5],因为p=&a,也即是p的类型.所以&a+1=&a+sizeof(A),其中A为int[5]:(把A=int[5]代入A* p,即相当于int(*p)[5]).所以&a+1=&a的地址值+5*4字节,即变为数组a的结束地址的下一个地址(即&a[5]),&a+1仍是int (*)[5]类型,经(int *)(&a+1)强制转化为int*,赋值给ptr.后面的ptr-1=ptr-sizeof(int)=ptr的地址值-4个字节,即变为数组a的最后一个元素的地址&a[4],*(ptr-1)即为a[4],故输出为5.
而a+1=a+sizeof(int):(此处a退化为int*,故对于A* p,A为int)=a的地址值+4个字节,即是&a[1],则*(a+1)即a[1],故输出2.

又如:
double t[]={1, 2, 578, 111,90} ;
double *pt= &t[3];//指向值为111
int *ptInt= reinterpret_cast< int * > (pt);
char *ptCh= reinterpret_cast< char * > (pt);
cout<< *( pt- 1)<< "\t"<< *(reinterpret_cast<double*>(ptInt-2))<<"\t"<<
*(reinterpret_cast<double*>(ptCh-8));//最后输出结果全为578
---------------------
void Fun( int *p)与void Fun( int p[])是一样的,即函数列表中的数组此时退化成了指针

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254152.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中继承thread类与实现Runnable接口的区别

Java中线程的创建有两种方式&#xff1a; 1&#xff0e; 通过继承Thread类&#xff0c;重写Thread的run()方法&#xff0c;将线程运行的逻辑放在其中 2&#xff0e; 通过实现Runnable接口&#xff0c;实例化Thread类 在实际应用中&#xff0c;我们经常用到多线程&#xff0c;…

【VMware vSAN 6.6】6.2.启用性能服务:vSAN硬件服务器解决方案

目录 1. 简介 1.1.适用于HCI的企业级存储2. 体系结构 2.1.带有本地存储的服务器2.2.存储控制器虚拟系统套装的缺点2.3.vSAN在vSphere Hypervisor中自带2.4.集群类型2.5.硬件部署选项3. 启用vSAN 3.1.启用vSAN3.2.轻松安装3.3.主动测试4. 可用性 4.1.对象和组件安置4.2.重新构建…

Android eclipse导入项目后出现Unable to resolve target #39;android-17#39;解决方法

eclipse导入项目后出现Unable to resolve target android-17解决方法。在最后附带还有一种编译逻辑不成功情况解决方法。 一、问题情况 二、解决的方法 1、改动项目的目标版本号与当前Android sdk相相应的版本号 2、自己主动修复一下项目 三、这个问题不是上面的。是另外情况&a…

多个圆点,鼠标选取两个,求两个点的距离,用于计算像素尺寸(halcon实现)

read_image (Image, C:/Users/22967/Desktop/晶圆找位置/0.bmp) dev_close_window () dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle) dev_display (Image)binary_threshold (Image, Region1, max_separability, dark, UsedThreshold) connection (Region1, C…

修改UBOOT和LINUX调试串口(TI达芬奇芯片--DM6467)

Posted on 2011-10-31 10:53 jamiedu 阅读(889) 评论(0) 编辑 收藏 1.1 概述 TI针对DM6467提供的UBOOT和内核默认都是串口0作为调试串口输出的&#xff0c;但现在我需要使用DM6467的UART0的modem功能&#xff0c;所以修改代码&#xff0c;改变调试串口为串口2。 需要修改的主要…

Java List与数组之间的转换

http://blog.csdn.net/kingzone_2008/article/details/8444678转载于:https://www.cnblogs.com/longshiyVip/p/5985981.html

受欢迎的五个开源可视化工具——你的选择是?

摘要&#xff1a;大数据时代&#xff0c;数据为王&#xff0c;还在对一堆数据而发愁吗&#xff1f;试试可视化工具吧&#xff0c;相信本文提到的五款工具有一款能够帮助到你。人工智能时代&#xff0c;数据和算法以及硬件资源是非常重要的&#xff0c;相关行业的大公司也越来越…

halcon车刀崩边检测

list_files (新建文件夹, files, Files) read_image (Image, Files[0]) dev_close_window () get_image_size (Image, Width, Height) dev_open_window (0, 0, Width/1.5, Height/1.5, black, WindowHandle) dev_set_draw (margin) dev_set_colored (12) for Index:0 to |Files…

FFMPEG解码264文件步骤

本文以H264视频流为例&#xff0c;讲解解码流数据的步骤。 为突出重点&#xff0c;本文只专注于讨论解码视频流数据&#xff0c;不涉及其它&#xff08;如开发环境的配置等&#xff09;。如果您需要这方面的信息&#xff0c;请和我联系。 准备变量 定义AVCodecContext。如果…

Storm概念学习系列之storm的特性

不多说&#xff0c;直接上干货&#xff01; storm的特性 Storm 是一个开源的分布式实时计算系统&#xff0c;可以简单、可靠地处理大量的数据流。 Storm支持水平扩展&#xff0c;具有高容错性&#xff0c;保证每个消息都会得到处理&#xff0c;而且处理速度很快&#xff08;在一…

Confluence 6 配置服务器基础地址示例

2019独角兽企业重金招聘Python工程师标准>>> 如果 Confluence 的安装是没有安装在非根目录路径&#xff08;这个是上下文路径&#xff09;&#xff0c;然后服务器基础 URL 地址应该包括上下文地址。例如&#xff0c;你的 Confluence 正在运行在下面的地址&#xff1…

BootstrapValidator验证

bootstrap&#xff1a;能够增加兼容性的强大框架. 因为项目需要数据验证&#xff0c;看bootstrapValidator 还不错&#xff0c;就上手一直&#xff0c;完美兼容&#xff0c;话不多说。 需要引用css&#xff1a; bootstrap.min.css bootstrapValidator.min.css js: jquery-1.10.…

基于ARM9的视频采集传输系统

http://www.ic37.com/htm_tech/2007-11/77189_618093.htm

halcon找矩形顶点的一种方法

主程序&#xff1a; read_image (Image11, 11)*画仿射矩形 dev_set_color (green) draw_rectangle2 (3600, Row, Column, Phi, Length1, Length2)*生成仿射矩形xld gen_rectangle2_contour_xld (Rectangle, Row, Column, Phi, Length1, Length2) *找顶点工具&#xff08;基于卡…

老男孩linux运维50期

一、自我介绍&#xff1a;我是来自老男孩Linux运维脱产50期的杨国峰&#xff0c;我以前是学软件编码的&#xff0c;但在大学里基本没怎么学&#xff0c;每一门课都一知半解的&#xff0c;甚至有些连软件都不会装&#xff0c;在校期间&#xff0c;我对JAVA、网页设计等都不感兴趣…

博客收藏

http://www.dreamfairy.cn/blog/category/unity3d/转载于:https://www.cnblogs.com/wantnon/p/5989843.html

移动开发平台性能比較

jquerymobile是一个mobile平台下的js框架,跟phonegap没有一毛钱关系.phonegap实际上在国内占有率不高的,非常多人为了体验喜欢做传统的原生手机应用. 而Webapp如今的占有率越来越少,由于越来越多的人不喜欢用手机浏览器去体验专门为移动平台搭建的站点.我认为你的比較对象应该是…

H264关于RTP协议的实现

完整的C&#xff0f;S架构的基于RTP&#xff0f;RTCP的H&#xff0e;264视频传输方案。此方案中&#xff0c;在服务器端和客户端分别进行了功能模块设计。服务器端&#xff1a;RTP封装模块主要是对H&#xff0e;264码流进行打包封装&#xff1b;RTCP分析模块负责产牛和发送RTCP…

华为数通HCIE面试题目解密系列之RSTP边缘端口

以下是华为数通面试考试的一道真题&#xff0c;原题如下&#xff1b; 请举例说明 stp 的 edge port 的作用,用在什么场景&#xff0c;并且使用 edge port 会碰到什么问题&#xff0c;怎么解决和防止&#xff1f; 提到边缘端口&#xff0c;我们是在NP课程的交换部分第一次接触&a…

VS2013 Pro版本密钥

Visual Studio Professional 2013 KEY&#xff08;密钥&#xff09;&#xff1a; XDM3T-W3T3V-MGJWK-8BFVD-GVPKY 转载于:https://www.cnblogs.com/Mysterious/p/5990358.html