C语言 为什么数组名可以php 输出数组China 求大佬指教

新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
大富大贵, 积分 11658, 距离下一级还需 8342 积分
论坛徽章:11
本帖最后由 Ager 于
13:03 编辑
浅谈一下C语言中的指针与数组的关系
_HellAngel_
在函数定义中,形式参数
是等价的。我们通常更习惯于使用后一种形式,因为它比前者更直观地表明了该参数是一个指针。
/* 这边我的一个想法是,指针和数组,用起来是不是基本上是分不开的,而且结合起来更简洁?今后的实践中可能会明白。 */
在C语言中,指针与数组(或许,可以更为具体地说:指针标识符与数组标识符)之间关系紧密。
为了弄清楚这个问题,我们必须在一开始,清楚地把握关于“标识符”这个范畴的直观印象。
一般的教科书,在它们阐释“标识符”的章节中,仅仅强调了标识符的组成规则,诸如:组成一个合法的标识符所能采用的字符是哪些、标识符不能以数字开头、标识符不能与语言现有的关键字重复、标识符对于组成它的字符的大小写是敏感的 …… 等等。
然而在这里,我们将要从完全不同的领域,来理解关于“标识符”的一些很重要、很关键的事情。我们依然遵循„Zu den Sachen selbst!“的思路。
首先,令一些符合标识符之组成规则的字符们,成为(to being)一个真正的标识符的那个being,在C语言中,叫做:声明器(Declarator)。
一个非常简单的声明器,体现在形如这样的一则声明(A Declaration)中:T D复制代码其中,“T”指明了“D”是什么“类型”的,而“D”则可以是一个标识符。“T”与“D”两下彼此阐释:D是一个T,或D是一个“T的”;T作为一个抽象观念,在D上得以实例化。
当上面的“D”是一个单纯的标识符的时候,我们就可以说:此标识符在这则声明中是一个“简单声明器”。这一类的例子,很容易理解,如下面的一行声明所呈现出来的:
/* 声明行 1 */
复制代码请注意:简单声明器之得以合法地被利用,其首要前提是:程序提供了足够完整与可靠的关于前者的类型信息。在上面的“一则声明”例子中,这种信息由“T”这个部分呈现。在【声明行 1】中,由“int”这个“类型指定符(Type Specifier)”呈明。
简单声明器,以及一些其他相对简单的声明器,统称为“直接声明器(Direct-Declarator)”。
直接声明器与一对方括号,是“数组声明器(Array Declarator)”必须具备的两个组成部分。
我在这里,之所以如此强调,其实,是为了告诉大家:数组声明器中的方括号的存在,是组成前者的一个必要(但不充分)条件。
而我之所以要告诉大家这一点,是因为:
在国内一些知名的程序员社区(如CSDN)中,充斥着大量这样的见解(或说法) —— “在声明数组时,那个指明下标的方框号 …… ”
也就是说,不少人都认为数组声明器中的那对方括号具有“下标”的含义。
而我要告诉你的是:数组声明器的那对方括号仅是组成前者的一个必要条件(或一个直观上的特征)。它与“下标操作符”,两者完全不是一回事!
在C语言中,用来表征一个数组声明器,以及使得一个数组元素成为左值,都采用以及可以采用“方括号”这对字符 —— 你干脆这样认为吧 —— 这只是一个巧合,而没有什么必然联系!
类似地,用来表征一个指针声明器的“指针符”,以及令程序可以透过指针去Handle一个内存对象并使得表达式成为左值的那个“间接访问操作符”,都采用“星号”这个字符,但两者的含义截然不同。
作为下标操作符的方括号,其真确含义是:
下标表达式:a[b]复制代码永远可以准确地对应于表达式(当然其中操作数的类型须合乎规则):*(a+b)复制代码这种语言特性,决定了我们可以利用下标表达式,通过指明数组名(数组标识符)与某个作为下标的整数,来使得数组中的某个元素,成为左值。
现在,我们回到数组声明器和它里面的那对方括号。
在某些情况下,C语言处理数组的时候,需要程序以某种恰当而可靠的方式,呈明当事数组的规模/长度(如数组所容纳的元素之数量)。
根据这个原则,我们不难理解以下结论:
『(i)我们应该利用数组声名器中的方括号,来呈明当事数组的规模,除非
(ii)我们可以利用其他某些恰当而可靠的方式,来呈明当事数组的规模,有如:char MyFullName[] = &Larry Ageratum Westernwall&;复制代码即数组声明器所在的当则声明,具备一个可以可靠地计算出当事数组规模的初始化部分。
又如:extern char X[][123];
……
static char X[321][123];复制代码即数组声明器所在的当则声明,并不具备定义的功能,该数组声明器仅作为一则“引用性声明”的一部分。
(iii)数组声名器在一个根本不需要呈明当事数组的规模的场合中,有如,在函数声明器中:void foo(char UserFullName[])复制代码这里无需呈明作为形式参数的数组UserFullName的规模,因为:作为函数形式参数的数组声明器,实际所期盼的,是一个指向char的指针,即上面的声明行,等同于void foo(char *UserFullName)复制代码也就是说,C语言中的函数,天然地不关心作为参数的数组的规模。(甚至你可以认为:以参数作为函数的视阈,函数将看不到任何“数组状”的对象。)鉴于这种特性,若有必要向函数呈明事数组的规模,应该为函数设置其他的(独立的)参数作为附加,比如设置一个整数类型的参数,用以令函数可以获悉一些关于数组规模的信息(可以是当事数组的完整规模,也可以是某种“起讫(截断)位置”)。
上面,我们比较详细地,讨论了数组标识符的在“to being”上的一些原理。
至此,我们还须要总结一些事情:
(1)数组标识符是一种标识符。(2)一个单纯的标识符是简单声明器。(3)简单声明器是直接声明器的一种。
(4)数组声明器必须包含一个直接声明器与一对方括号。
(5)数组声明器中的方括号,不是数组标识符的一部分。
下面,我们讨论一下,数组标识符,在C语言的表达式中的“to be done”。
在这件事情上,C语言的法则是:
(一)数组标识符,若出现在表达式中,则该标识符所体现出来的类型,就从原本在最初的声明中由类型指定符所确定的“T的数组(T [])”,转换为“指向T的指针(T *)”,后者总是指向当事数组的首个元素。除非
(二)数组标识符,若作为操作符sizeof或取地址操作符&的操作数的时候。数组标识符若作为操作符sizeof的操作数,那么sizeof表达式返回整个数组的长度(字节数量);数组标识符若作为操作符&的操作数,那么&表达式返回一个指向数组的指针(T(*)[])。
我们分别讨论以上两条法则。
第一条法则,是我们在程序中可以利用下标操作符将数组元素成为左值的基础。在下标表达式中,一侧(不一定是左侧)的数组标识符被转换为指向数组首个元素的指针,另一侧(不一定是右侧)的整数类型的表达式,实际上成为了指针加法的一个操作数。根据指针加法可以适用的加法交换律,作为左值的MyFullName[3]复制代码与3[MyFullName]复制代码是等效的。
此外,当我们定义了如下函数:void foo(char *s)复制代码或void foo(char s[])复制代码以及如下数组:char a[5]复制代码而通过foo(a)复制代码去调用函数foo的时候,a在这里,即是指向数组a的首个元素的指针。所以这个调用,与foo(&a[0])复制代码是等效的。
请注意:a在这里,并不是操作符&的操作数,a[0]才是。下标操作符的优先级属于最高一级,而操作符&的则属于次最高一级。
有些初学者,或许受其他编程语言中关于数组用法的污染,有一种倾向,即用“a[]”或“a[5]”这样的写法,在表达式中呈现一个关于“数组a之整体”的概念 —— 这是错误的!
如果使用foo(a[])复制代码来调用函数foo,那么将产生下标操作符缺失操作数的错误。
如果使用foo(a[5])复制代码来调用函数foo,那么,这里被传入函数的参数将是数组a中下标为5的元素的值。显然这个元素处于某种“越界”的位置,但比越界更加糟糕的是,这个值的类型是char,而不是函数foo由其定义所期盼的char *。
现在我们回到最初的例子:
函数foo的参数声明部分,即char s[]复制代码或char *s复制代码为什么能让我们感到我们可以由一个“数组状”的形式参数s直接地俘获到了一个作为实际参数的数组a呢?
也就是说,我们感到,我们可以将作为实际参数的数组a之整体“耦合般地投放”到作为形式参数的数组s之整体上,这是为什么?
其实,这种“耦合般地投放”是一种错觉。造成这种错觉的根本原因,并非在于函数的参数声明部分,而是在于我们调用函数的部分。
也就是说,这种错觉,仅发生在我们这样调用函数foo的时候:foo(a)复制代码这里,调用函数时所设置的参数,是一个作为表达式存在的数组标识符a,根据上面的法则(一),这里的参数实际上是一个指向数组a首个元素的指针。那么,我们在函数foo这端,在某种意义上,标识符s自然也具有与数组标识符a相当的地位 —— 即一个本质上的指针标识符被当作一个影子般的数组标识符来使用。不过,当我们在函数foo内部使用sizeof(s)复制代码的时候,只能获得某一个指针的长度,而无法达到sizeof(a)复制代码的效果了。(这映证了这麽一个事实:C语言的实现机构中,必定有一块地方,记录了数组a的存在规模,即a作为一个数组之整体的存在,在实现机构中有一席之地。)
打破上述错觉的另外一招是,我们改变调用函数foo所采用的参数。比如,我们这样来调用函数foo:foo(a+2)复制代码或foo(&a[2])复制代码即,我们利用“指针加法”或“操作符&与操作符[]配搭使用”来构造一个新的指针,将其作为实际参数传给函数foo,此时,在函数foo内部,就再也没有“数组a的影子般的数组标识符”了。
现在,我们再回到函数声明中关于参数声明的这一层。
我们已经明白:在函数的参数声明中,形如s[]复制代码这样的“数组状”的声明器,实际上终将被“转化”为一个指针声明器,即:一个表面上的数组标识符,实际上是作为一个指针标识符而存在。(同时,一切关于数组存在规模的信息,被蔽弃。)
C语言为什么要有这样的“转化法则”?
在以前的帖子里,我们已经知道:C语言的函数策略,使得函数治下的变量的数据,可以是一份由形式参数机构所俘获的实际参数的数据的副本。从实现的角度看,这些副本性的数据,存在于内存空间中属于当事函数的帧(Frame)上。
显然,副本性的数据的数量/规模越大,实现在函数帧的开销上,就越大。
而数组的存在,天然地就带有“规模性”的目的因素。
也就是说,如果令函数内部为数组之整体承受其私有副本的话,函数帧将占用相应的规模性资源。
C语言没有采用上面这种策略,而是采用了另外一种:
当程序企图将数组作为参数传入参数(准确地说,是期望利用含有一个单纯的数组声明器的参数声明来俘获目标数组)的时候,被调用函数仅利用其形式参数机制,承建并维护一个该数组的基性地址(指针)的私有副本。这样的副本性数据,给函数帧带来的开销,是非常小的。
在这种情况下,由于被调用函数治下拥有一个关于作为参数的数组的指针,这意味着,函数内部至少可以有一个“完全有把握”去Handle目标数组元素的左值,也就是说,该函数可以间接地实施(等效于直接地)读取或刷写目标数组元素的数据,而不是它(们)的副本。—— 这里,蕴涵了一个至关重要的前提性事实:在C语言中,数组元素在内存空间上的分布形势,与指针运算值域的分布形势,两者是严格地一致的。
显然,这种策略满足了某种现实上的便利性和经济性要求。而为了符合这种策略,就有了前述的“转化法则”。
而第二条法则,有助于我们获取某些关于目标数组之整体的信息(如数组之规模)。
以上,仅供参考,呵呵 ——:)
同样,本帖子须经
大虾等诸位高人审订一下。尔后,你才可放心阅读无虞:)
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
小富即安, 积分 3236, 距离下一级还需 1764 积分
论坛徽章:5
回顾起来,这个就是成长的过程。
白手起家, 积分 45, 距离下一级还需 155 积分
论坛徽章:0
C语言博大精深的,
& & 单单一个单词就能引申出长篇大论呀。
白手起家, 积分 4, 距离下一级还需 196 积分
论坛徽章:0
c语言中的指针与数组
/pointers_and_arrays.html
白手起家, 积分 10, 距离下一级还需 190 积分
论坛徽章:0
有点专业,不过值得看下。
大富大贵, 积分 11658, 距离下一级还需 8342 积分
论坛徽章:11
lin5161678 发表于
这个a的数据类型是int[5]
&a是 int(*)[5]
&a+1就是 +sizeof(int[5])
为什么解释不了
不止能解释 还能解释得很清楚
好! 顶一下:)
大富大贵, 积分 10355, 距离下一级还需 9645 积分
论坛徽章:0
& & C语言中同一个符号在不同的Context中有不同的含义确实是真正理解C语言的一个关键,即使在最简单的情况下也是如此
论坛徽章:2
提示: 作者被禁止或删除 内容自动屏蔽
丰衣足食, 积分 776, 距离下一级还需 224 积分
论坛徽章:0
我表示非常惭愧。。。
大富大贵, 积分 11658, 距离下一级还需 8342 积分
论坛徽章:11
sqfasd 发表于
回复 101# lin5161678
您还没解释,a == &a呢
参照91楼和98楼的观点,能解释吗a == &a复制代码The Warning says it all.....
编译器会先抱怨你一下,然后,它还是默默流泪地满足你的欲望。。。。。。
呵呵。。。。
您需要登录后才可以回帖"c语言数组名代表什么"的糗事
你可能感兴趣:
糗事百科为大家收集了很多的c语言数组名代表什么的糗事,各种关于c语言数组名代表什么的爆笑经历、尴尬时刻和开心视频,想持续关注c语言数组名代表什么的糗事就收藏本页吧.c语言字符数组与字符串的使用详解
字体:[ ] 类型:转载 时间:
本篇文章是对c语言中字符数组与字符串的使用进行了详细的分析介绍,需要的朋友参考下
1、字符数组的定义与初始化字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素。char str[10]={ 'I',' ','a','m',' ',‘h','a','p','p','y'};即把10个字符分别赋给str[0]到str[9]10个元素如果花括号中提供的字符个数大于数组长度,则按语法错误处理;若小于数组长度,则只将这些字符数组中前面那些元素,其余的元素自动定为空字符(即 '\0' )。
2、字符数组与字符串在c语言中,将字符串作为字符数组来处理。(c++中不是)在实际应用中人们关心的是有效字符串的长度而不是字符数组的长度,例如,定义一个字符数组长度为100,而实际有效字符只有40个,为了测定字符串的实际长度,C语言规定了一个“字符串结束标志”,以字符'\0'代表。如果有一个字符串,其中第10个字符为'\0',则此字符串的有效字符为9个。也就是说,在遇到第一个字符'\0'时,表示字符串结束,由它前面的字符组成字符串。系统对字符串常量也自动加一个'\0'作为结束符。例如"C Program”共有9个字符,但在内存中占10个字节,最后一个字节'\0'是系统自动加上的。(通过sizeof()函数可验证)有了结束标志'\0'后,字符数组的长度就显得不那么重要了,在程序中往往依靠检测'\0'的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。当然,在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度。(在实际字符串定义中,常常并不指定数组长度,如char str[ ])说明:'\n'代表ASCII码为0的字符,从ASCII码表中可以查到ASCII码为0的字符不是一个可以显示的字符,而是一个“空操作符”,即它什么也不干。用它来作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志。对C语言处理字符串的方法由以上的了解后,再对字符数组初始化的方法补充一种方法——即可以用字符串常量来初始化字符数组:char str[ ]={"I am happy"};&&&&&& 可以省略花括号,如下所示char str[ ]="I am happy";注意:上述这种字符数组的整体赋值只能在字符数组初始化时使用,不能用于字符数组的赋值,字符数组的赋值只能对其元素一一赋值,下面的赋值方法是错误的&&&&&&&&&&&& char str[ ];&&&&&&&&&&& str="I am happy";不是用单个字符作为初值,而是用一个字符串(注意:字符串的两端是用双引号“”而不是单引号‘'括起来的)作为初值。显然,这种方法更直观方便。(注意:数组str的长度不是10,而是11,这点请务必记住,因为字符串常量"I am happy"的最后由系统自动加上一个'\0') 因此,上面的初始化与下面的初始化等价char str[ ]={'I',' ','a','m',' ','h','a','p','p','y','\0'};而不与下面的等价char str[ ]={'I',' ','a','m',' ','h','a','p','p','y'};前者的长度是11,后者的长度是10.说明:字符数组并不要求它的最后一个字符为'\0',甚至可以不包含'\0',向下面这样写是完全合法的。char str[5]={'C','h','i','n','a'};++++++++可见,用两种不同方法初始化字符数组后得到的数组长度是不同的。
#include &stdio.h&void main(void){char c1[]={'I',' ','a','m',' ','h','a','p','p','y'};char c2[]="I am happy";int i1=sizeof(c1);int i2=sizeof(c2);printf("%d\n",i1);printf("%d\n",i2);}结果:10&& 11
3、字符串的表示形式在C语言中,可以用两种方法表示和存放字符串:(1)用字符数组存放一个字符串&&&&&&&&&&char str[ ]="I love China";(2)用字符指针指向一个字符串&&&&&&&&&&char* str="I love China";对于第二种表示方法,有人认为str是一个字符串变量,以为定义时把字符串常量"I love China"直接赋给该字符串变量,这是不对的。C语言对字符串常量是按字符数组处理的,在内存中开辟了一个字符数组用来存放字符串常量,程序在定义字符串指针变量str时只是把字符串首地址(即存放字符串的字符数组的首地址)赋给str。两种表示方式的字符串输出都用printf("%s\n",str);%s表示输出一个字符串,给出字符指针变量名str(对于第一种表示方法,字符数组名即是字符数组的首地址,与第二种中的指针意义是一致的),则系统先输出它所指向的一个字符数据,然后自动使str自动加1,使之指向下一个字符...,如此,直到遇到字符串结束标识符 " \0 "。4、对使用字符指针变量和字符数组两种方法表示字符串的讨论虽然用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈。4.1、字符数组由若干个元素组成,每个元素放一个字符;而字符指针变量中存放的是地址(字符串/字符数组的首地址),绝不是将字符串放到字符指针变量中(是字符串首地址)4.2、赋值方式:&&&& 对字符数组只能对各个元素赋值,不能用以下方法对字符数组赋值&&&& char str[14];&&&& str="I love China";&&&& (但在字符数组初始化时可以,即char str[14]="I love China";)&&&& 而对字符指针变量,采用下面方法赋值:&&&& char*&&&& a="I love China";&&&& 或者是 char* a="I love China";&&&&&& 都可以4.3、对字符指针变量赋初值(初始化):&&&&&&&& char* a="I love China";&&&&& 等价于:&&&&&&&&&& char*&&&&&&&&&& a="I love China";而对于字符数组的初始化&&&&&&&&& char str[14]="I love China";不能等价于:&&&&&&&& char str[14];&&&&&&&& str="I love China"; (这种不是初始化,而是赋值,而对数组这样赋值是不对的)4.4、如果定义了一个字符数组,那么它有确定的内存地址;而定义一个字符指针变量时,它并未指向某个确定的字符数据,并且可以多次赋值。
5、字符串处理函数 5.1char *strcat(char *str1,const char *2 );char *strcat(char *strDestination,const char *strSource );功能:函数将字符串str2 连接到str1的末端,并返回指针str1注:连接前两个字符串的后面都有一个' \0 ',连接时将字符串1后面的 ' \0 ‘去掉,只在新串最后保留一个 ' \0 ‘5.2char *strcpy(char *str1,const char *2 );char *strcpy(char *strDestination,const char *strSource );功能:复制字符串strSource中的字符到字符串strDestination,包括空值结束符。返回值为指针strDestination。注:1、“字符数组1”必须写成数组名形式,“字符串2"可以是字符数组名,也可以是一个字符串常量2、复制时连同字符串后面的 ' \0 ' 一起复制到数组1中3、不能用赋值语句直接将一个字符串常量或者字符数组直接赋给一个字符数组(同普通变量数组是一样的),而只能用strcpy函数处理。4、可以用strcpy函数将字符串2中的前若干个字符复制到字符数组1中去。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具各位大佬用的是什么编程软件啊求安利【c语言吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:541,093贴子:
各位大佬用的是什么编程软件啊求收藏
各位大佬用的是什么编程软件啊求安利
c语言哪里好?达内,0基础入学,无专业要求,先就业后付款,毕业&薪&起点.c语言哪里好?达内C语言课程,独创TTS8.0授课模式,一线名师授课.
vs2017codeblocks
登录百度帐号推荐应用c语言 数组习题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
c语言 数组习题
&&学习c语言的同学可以看看,里面的题比较经典,做了以后2级没问题
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩12页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢}

我要回帖

更多关于 php 输出数组 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信