user-0 提问: C语言中的数组和指针到底啥关系啊

回复:
user: user-1
content: 讨论很热烈。。。。。。

user: user-2
content: 先学汇编，再学C 。

user: user-3
content: 数组是数组  指针是指针 数组用来暂时存储数据的 指针跟地址有关系

user: user-4
content: 作为一个新手，我表示看不懂啊啊啊

user: user-5
content: 引用 89 楼 Red_Strings 的回复:打起来了怎么还， 楼主刚开始学千万别太深入地研究，到后来你就算明白了，循序渐进地学， 说实话谭浩强那本c语言书讲这方面讲的挺好，最起码我这种智商都看懂了。谭C错误太多 不值得推荐  自己看就好 不要宣传 会误人子弟

user: user-5
content: 引用 88 楼 _Saoke 的回复:不同之处:在某些特定情况下，指针的引用操作要比数组的引用操作效率更高一些 目测你说反了  数组效率更高  某些特定情况 指针能达到数组的效率

user: user-6
content: 引用 95 楼 lin5161678的回复:[quote=引用 94 楼 _Saoke 的回复:] [quote=引用 91 楼 lin5161678的回复:][quote=引用 88 楼 _Saoke 的回复:] 不同之处:在某些特定情况下，指针的引用操作要比数组的引用操作效率更高一些 目测你说反了  数组效率更高  某些特定情况 指针能达到数组的效率  [/quote] 建议你看一下c和指针中，指针与下标这一小节的内容[/quote] 建议你看看汇编 简单介绍一下可能的实现  int arr[10], *p = arr; arr[5]=5 求出偏移4*5 存到寄存器 对 数组地址+寄存器 进行赋值   p[5]=5 一样会有计算偏移的操作 存到寄存器 然后把p保存的数据从内存读取到另一个寄存器 最后通过2个寄存器保存的数据 计算出地址 进行赋值操作  当然会有各种不同的实现方式  这里仅通过某种可能的实现方式 进行分析 可以看到  p[5] 会比 arr[5] 多一步 读取p的数据到寄存器的操作 为什么会认为 p[5] 效率优于 arr[5] 呢? [/quote] 好的，我会去阅读的，谢谢

user: user-7
content: 打起来了怎么还， 楼主刚开始学千万别太深入地研究，到后来你就算明白了，循序渐进地学， 说实话谭浩强那本c语言书讲这方面讲的挺好，最起码我这种智商都看懂了。

user: user-8
content: 字符串应该是数组吧， C89 里的描述是这样的 3.1.4 String literals  Syntax            string-literal:                   " s-char-sequence<opt>"                   L" s-char-sequence<opt>"            s-char-sequence:                   s-char                   s-char-sequence s-char            s-char:                   any member of the source character set except                    the double-quote ", backslash \, or new-line character                    escape-sequence  Description     A character string literal is a sequence of zero or more multibyte characters enclosed in double-quotes, as in xyz.  A wide string literal is the same, except prefixed by the letter L.     The same considerations apply to each element of the sequence in a character string literal or a wide string literal as if it were in an integer character constant or a wide character constant, except that the single-quote ' is representable either by itself or by the escape sequence \', but the double-quote shall be represented by the escape sequence \.  Semantics     A character string literal has static storage duration and type ``array of char ,'' and is initialized with the given characters.  A wide string literal has static storage duration and type ``array of wchar_t,'' and is initialized with the wide characters corresponding to the given multibyte characters.  Character string literals that are adjacent tokens are concatenated into a single character string literal.  A null character is then appended. /19/ Likewise, adjacent wide string literal tokens are concatenated into a single wide string literal to which a code with value zero is then appended.  If a character string literal token is adjacent to a wide string literal token, the behavior is undefined.

user: user-9
content: 理论上数组效率更高 ，数组名直接代表一个地址，所以对数组元素的访问可以直接生成mov [xxxx+index], value这样的指令，而指针访问需要做一次解引用 mov reg,[ptr]; mov [reg],value; 但是如果编译器优化把数组首地址或者指针值缓存到寄存器中（在一段代码中保持不变），则两者生成同样效率的代码

user: user-5
content: 引用 94 楼 _Saoke 的回复:[quote=引用 91 楼 lin5161678的回复:][quote=引用 88 楼 _Saoke 的回复:] 不同之处:在某些特定情况下，指针的引用操作要比数组的引用操作效率更高一些 目测你说反了  数组效率更高  某些特定情况 指针能达到数组的效率  [/quote] 建议你看一下c和指针中，指针与下标这一小节的内容[/quote] 建议你看看汇编 简单介绍一下可能的实现  int arr[10], *p = arr; arr[5]=5 求出偏移4*5 存到寄存器 对 数组地址+寄存器 进行赋值   p[5]=5 一样会有计算偏移的操作 存到寄存器 然后把p保存的数据从内存读取到另一个寄存器 最后通过2个寄存器保存的数据 计算出地址 进行赋值操作  当然会有各种不同的实现方式  这里仅通过某种可能的实现方式 进行分析 可以看到  p[5] 会比 arr[5] 多一步 读取p的数据到寄存器的操作 为什么会认为 p[5] 效率优于 arr[5] 呢?

user: user-6
content: 引用 91 楼 lin5161678的回复:[quote=引用 88 楼 _Saoke 的回复:] 不同之处:在某些特定情况下，指针的引用操作要比数组的引用操作效率更高一些 目测你说反了  数组效率更高  某些特定情况 指针能达到数组的效率  [/quote] 建议你看一下c和指针中，指针与下标这一小节的内容

user: user-10
content: 要了解指针和数组，首先要先对内存管理有所了解。  系统用一个以字节为单位的虚拟的地址表来描述和管理整个物理内存，分配内存的过程就是给定某个空闲的地址区间，将这块地址区间与相应字节数的某小块空闲的物理内存建立映射。这段地址区间的首地址就是CPU定位这块内存的凭据，或者说是“门牌号”。那么相对的，从这个首地址开始向后偏移若干字节的偏移地址，就可以定位到这小块内存空间的局部。  内存并没有数据类型之分，内存只会存储二进制数据流。举个简单的例子：一个字符占一个字节，一个字节有8个二进制位，所以字符在内存中存储的实体是一段8位的二进制流0000 0000，每一位上只可能是0或1，于是乎8个二进制位可以表示2的8次方个不同的内容，字符只是这段二进制流参照ASCII编码后在人类眼中的表现形式。我们在源代码中设定数据类型决定了我们从给定的首地址向后读取多少字节的内容，比如一个int类型占4个字节，也就是4*8=32个二进制位：0000 0000 0000 0000 0000 0000 0000 0000，我们如果用int来读取就会从首地址向后读取4个字节的内容，但是如果我们强行用char类型来读取这段内存，我们只会从首地址开始向后读取一个字节的内容，也就是只读到0000 0000。  我们源代码中的变量名可以指代一小块内存，编译器会按照固定的结构帮我们把源代码编译成一个“内存模板”，程序运行的时候会产生一个进程，系统根据这个模板为进程分配一整块内存。然后按照模板往内部不同区块塞入初始数据。变量名会被翻译成相对整个进程内存内部某个区块的偏移地址。比如已初始化的全局变量和static静态变量存在进程的全局区；未初始化的全局变量和static静态变量存在BSS段；普通局部变量则存储于栈区。它们都是一个相对地址。  数组名也是一种变量名，也会被翻译成某个相对地址，虽然数组比单个的变量内存要大，但是由于数据类型的限制，数组每次只能读取一个数据类型单位的长度，比如：int arr[10]，一共占据4*10=40个字节的长度，但是每次按int类型只会读取4个字节。C/C++提供了两种访问方式，一种是下标访问，如：arr[3];一种是地址偏移访问,如：arr + 3。arr是整个数组的起始地址，整个数组的地址当然也就是第一个元素的地址，或者说是“首地址”，arr[3]或者arr + 3就是在arr的基础上再向后累加3个int的跨度，以这个地址为起点向后访问一个int长度的内存。  只要有地址就可以找到对应的内存。  指针类型是一种特殊的类型，它通常被用来备份地址值。和数组名不同的是，数组名本身就代表了自己，而指针则支持充当了中介的工作，指针变量在自己的内存空间里存储了别的空间的地址，我们可以通过它存的地址找到与之对应的内存。从语言习惯上来讲，我们可以说指针指向了xxx，实际上是指针把xxx的地址备份了起来。  通过地址访问空间的原理都是一样的，所以指针和数组名在很多情况下操作是非常类似的。比如指针也支持下标访问，以及通过偏移地址来访问的方式。在传递参数的时候，如果参数类型是数组类型，也会默认当做指针来处理。比如： void fun(int arr[10]); 这个函数似乎规定了arr最多有10个，但是编译器并不加以理会，而是纯粹把它当做void fun(int* arr)来解释。

user: user-11
content: http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素 http://edu.csdn.net/course/detail/2455 C语言指针与汇编内存地址-二.函数 http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组 http://edu.csdn.net/course/detail/2517 C语言指针与汇编内存地址-四.三维数组

user: user-6
content: 简单的总结一下，一定会有一定的缺陷，希望大家谅解: 关系:数组名在进行运算操作的时候会隐式转化为指针；相似之处:数组名和指针可以以不同的方式对数据进行相同的引用；不同之处:在某些特定情况下，指针的引用操作要比数组的引用操作效率更高一些

user: user-12
content: 引用 9 楼 xx1959590935的回复:既然你这么说我就不说啥了。你开心就好。我不解释太多，你可以怼我。但我只想说，连数组和指针都不明白的人还说理解字节和内存。。真是美美哒。你开心就好。祝你在c语言这条路上越走越远。 刚接触c  学的一点皮毛而已

user: user-5
content: 引用 86 楼 sololie 的回复:学习编程不能跳过基本的计算机原理，如果你懂得内存原理，和数据结构的话，这根本不存在任何理解问题。数组是一种链表结构，表头首地址就是这种数据类型变量的地址，操作数组跟操作指针没有什么区别有点离谱了 你说线性结构没问题  链表结构是认真的?

user: user-12
content: 引用 3 楼 xx1959590935的回复:纠正几个错误，第一，你说的那个1234它不是数组，它是字符串，你往后学习就知道了，你会学到更多容器，然后回头看数组就会明白数组也是个容器，肯定是有名字的。 而且作为数组的名字，它指向的的肯定是数据的第一个元素，如果不是这样，那数组就没人敢用了。第二，我说它的名字是const类型不是说它能不能被赋值，而是它作为一个指向一串数据的指针，它的值是不能被改变的，严谨的说，我也不知道他是什么类型，不过这是新手最容易理解的解释，我试过了，确实不是const类型。既然知道的多那就多说点。我特意对数组和指针做过大量的测试，得出的结论简单点说就是，除了数组的名字不能被改变，数组功能的实现是完全可以用指针代替的，相反，指针也可以通过数组的方式访问。具体原理我就不说明太多了，仁者见仁 智者见智。(不考虑内存分配，下面会说道).  你可以通过指针访问数组的任何成员，你可以把数组作为指针参数传递。在容器方面数组和指针有一个绝对的相同点，他们储存数据都是有序的。再说说不同的。他们也有绝对的不同点，要不就不会出现数组这个东西了。数组的内存分配是固定的。你可以去理解下动态数组这个概念，你看看他的实现方法，说白了他的实现就是为一个指针开辟了一个某个类型特定数量的空间，你完全可以用malloc开辟同样的空间，在使用时和动态动态数组的使用不会有任何不一样，前提是你用的对。。。我这里没说关于内存的知识，手机要没电了，不继续码字了。有啥问题可以继续提。你去了解下字节和内存这个概念。深深的理解这两个概念，你就会发现新大陆。 能不能 用具体的程序  解释一下   我们小白 表示看不懂

user: user-13
content: 学习编程不能跳过基本的计算机原理，如果你懂得内存原理，和数据结构的话，这根本不存在任何理解问题。数组是一种链表结构，表头首地址就是这种数据类型变量的地址，操作数组跟操作指针没有什么区别

user: user-14
content: 指针变量用来存储地址，数组划分了一整块存储空间，而数组名一般就是该数组首地址(一维)，所以很多教材把他们放在一块讲，你可以把一维数组名当成一个指针，然后利用他和其他变量一起可以实现数组的调用