指针与数组

先看一个例子:

int a[10];
int *pa = $a[0];
pa++;

首先指针pa指向a[0]的地址,注意后缀运算符的优先级高于单目运算符,所以是取a[0]的地址,而不是取a的地址。然后pa++让pa指向下一个元素(也就是a[1]),由于pa是int *指针,一个int型元素占4个字节,所以pa++使pa所指向的地址加4,注意不是加1。

从前面的例子我们发现,地址的具体数值其实无关紧要,关键是要说明地址之间的关系(a[1]位于a[0]之后4个字节处)以及指针与变量之间的关系(指针保存的是变量的地址),现在我们换一种画法,省略地址的具体数值,用方框表示存储空间,用箭头表示指针和变量之间的关系。

                                                    

既然指针可以用++运算符,当然也可以用+、-运算符,pa+2这个表达式也是有意义的,如上图所示,pa指向a[1],那么pa+2指向a[3]

事实上,E1[E2] 这种写法和
(*((E1)+(E2)))
是等价的,*(pa+2) 也可以写成pa[2],pa
就像数组名一样,其实数组名也没有什么特殊的,a[2]之所以能取数组的第2个元素,是因为它等价于 *(a+2),关于数组的基本操作,当数组名做右值时自动转换成指向首元素的指针,所以a[2]和pa[2]本质上是一样的,都是通过指针间接寻址访问元素。

由于(*((E1)+(E2)))显然可以写成(*((E2)+(E1))),所以E1[E2]
也可以写成 E2[E1],这意味着2[a]、2[pa]这种写法也是对的,但一般不这么写。另外,由于a做右值使用时和&a[0]是一个意思,所以int *pa = &a[0] ;通常不这么写,而是写成更简洁的形式int*pa
=a;

C语言允许数组下标是负数,现在你该明白为什么这样规定了。在上面的例子中,表达式pa[-1]是合法的,它和a[0]表示同一个元素。

 

两个指针变量做比较运算(>、>=、<、<=、==、!=)表示什么意义?两个指针变量做减法运算又表示什么意义?

根据以往使用比较运算的经验,就应该猜到pa + 2 > pa,pa - 1 == a,所以指针之间的比较运算比的是地址,C语言正是这样规定的,不过C语言的规定更为严谨,只有指向同一个数组中元素的指针之间相互比较才有意义,否则没有意义。

那么两个指针相减表示什么?pa - a等于几?因为pa - 1 == a,所以pa - a显然应该等于1,指针相减表示两个指针之间相差的元素个数,同样只有指向同一个数组中元素的指针之间相减才有意义。两个指针相加表示什么?想不出来它能有什么意义,因此C语言也规定两个指针不能相加

在取数组元素时用数组名和用指针的语法一样,但如果把数组名做左值使用,和指针就有区别了。例如pa++是合法的,但a++就不合法,pa
= a + 1是合法的,但a = pa + 1就不合法。数组名做右值时转换成指向首元素的指针,但做左值仍然表示整个数组的存储空间,而不是首元素的存储空间,数组名做左值还有一点特殊之处,不支持++、赋值这些运算符,但支持取地址运算符&,所以&a是合法的。

 

如下,列举几种等价的函数原型:[如果参数是数组,则等价于参数是指针的形式]

1. void func(int a[10]) { ... }

2. void func(int *a) { ... }

3.  void func(int a[]) { .. }

参数写成指针形式还是数组形式对编译器来说没区别, 都表示这个参数是指针, 之所以规定两种形式是为了给读代码的人提供有用的信息,如果这个参数指向一个元素,通常写成指针的形式,如果这个参数指向一串元素中的首元素,则经常写成数组的形式. 

(指针就是数组?-->可以看这篇文章里的最后一个例子!)

时间: 2024-08-18 17:07:13

指针与数组的相关文章

一个关于指针和数组的问题

问题描述 一个关于指针和数组的问题 #define _CRT_SECURE_NO_WARNINGS#include ""stdlib.h""#include ""stdio.h""#include ""string.h"" int main(){ char buf1[100] = { 0 }; char buf2[100] = { 0 }; char *p1 = buf1; char *

指针与数组(二)

[例6-11]用指针法输入输出二维数组各元素.#include<stdio.h>main(){int a[3][4],*ptr;int i,j;ptr=a[0];for(i=0;i<3;i++)for(j=0;j<4;j++)scanf("%d",ptr++);/*指针的表示方法*/ptr=a[0];for(i=0;i<3;i++){for(j=0;j<4;j++)printf("%4d",*ptr++);printf("

指针与数组(一)

变量在内存存放是有地址的,数组在内存存放也同样具有地址.对数组来说,数组名就是数组在内存安放的首地址.指针变量是用于存放变量的地址,可以指向变量,当然也可存放数组的首址或数组元素的地址,这就是说,指针变量可以指向数组或数组元素,对数组而言,数组和数组元素的引用,也同样可以使用指针变量.下面就分别介绍指针与不同类型的数组. 6.4.1指针与一维数组 假设我们定义一个一维数组,该数组在内存会有系统分配的一个存储空间,其数组的名字就是数组在内存的首地址.若再定义一个指针变量,并将数组的首址传给指针变量

C语言之指针、数组和函数

基本解释 1.指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址):数组的本质则是一系列的变量. 2.数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变.指针可以随时指向任意类型的内存块,它的特征是"可变",所以我们常用指针来操作动态内存. 3.当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针. 问题:指针与数组 听说char a[]与char *a是一致的,是不是这样呢? 答案与分析: 指针和数组存在着一些本质的区别

C++指针和数组

数组的指针即整个数组在内存中的起始地址,而数组元素的指针是数组中某一元素所占存储单元的地址. 利用指针法引用数组元素能使目标程序质量高.占内存少.运行速度快. C++语言中规定:数组名就代表数组首地址,也就是数组第0号元素的地址.如 int a[10]; int *p; p=&a[0];/*与p=a,是等价的*/ p+i或a+i就是a[i]元素的存储地址,即它们都指向数组的第i号元素a[i].所以*(p+i)或*(a+i)就与a[i]是等价的.实际上,在编译时,编译程序把a[i]处理成*(a+i

c++-jna传递指针转换为数组问题

问题描述 jna传递指针转换为数组问题 最近在做jna相关问题,遇到一个问题:JNA调用c++接口,传递的是指针,在c++接口中给这个指针分配了一个数组空间,在java这边怎样将这个指针转换为数组?希望大神能解答 解决方案 解决了,又写了一个接口用于指针的自增,然后返回这个指针给java那边.但是需要遍历数组,消耗了一些性能

C++中的指针、数组指针与指针数组、函数指针与指针函数

C++中的指针.数组指针与指针数组.函数指针与指针函数 本文从初学者的角度,深入浅出地详解什么是指针.如何使用指针.如何定义指针.如何定义数组指针和函数指针,并给出对应的实例演示:接着,区别了数组指针与指针数组.函数指针与指针函数:最后,对最常混淆的引用传递.值传递和指针传递做了区处. C++中一个重要的特性就是指针,指针不仅具有获得地址的能力,还具有操作地址的能力.指针可以用于数组.或作为函数的参数,用来访问内存和对内存的操作,指针的使用使得C++很高效,但是指针也非常危险,使用不当会带来比较

c语言-数组指针指向数组的问题

问题描述 数组指针指向数组的问题 int main() { char a[5]={'A','B','C','D'}; char (*p3)[10] = &a; char (*p4)[10] = a; return 0; } int main() { char a[5]={'A','B','C','D'}; char (*p3)[3] = &a; char (*p4)[3] = a; return 0; } 这两个式子怎么理解啊?貌似指针这样指有点问题,面试题上看到的,也是醉的不行.p3+1

c语言-C语言中的指针和数组的初始化

问题描述 C语言中的指针和数组的初始化 char a[]=""abcdef"";char *p =""cdefg"";a[1]='A';p[1]='A'; 这段代码有什么问题?#include int main(){ char amessage[]=""now is the time""; char *pmessage = ""now is the time"

指针与数组的区别详解

 指针是C语言的精华,它是一柄"双刃剑",用的好与坏就看使用者的功力了.下面就一道测试题,看一下指针与数组的区别.   char *p1, *p2;char ch[12];char **pp; p1 = ch; pp = &ch; p2 = *pp; 问p1和p2是否相同       题目如上,找出其中的不妥之处.       首先,数组ch是没有初始化的.其次,一个比较隐含的地方是,数组名可以代表数组第一个元素的首地址,这个没有问题,但是,数组名并非一个变量,数组分配 完成后