指针和数组

  数组和指针有关系吗?一点关系也没有!大多数人认为它们有关系,那是因为大多数写C语言教材的作者通常会把数组和指针放在一起介绍。如果分开写,可能大部分人会掌握的更好(写在一起容易混淆)。唯一有一点点关系的就是:数组标记实际上是一种变相使用指针的方式。这是数组和指针之间爱恨情仇的前提吧。比如:数组名同时也是这个数组的第一个元素的地址,以下例子是正确的。

int array[10],这是一个数组,那么array == &array[0],这个是成立的。分析一下:array是这个数组的数组名,array[0]是数组的第一个元素,取第一个元素的地址&array[0],两者等价。都是代表数组首元素的内存地址,注意:这两个都是一个常量,不能使用自增自减运算符,例如array++是错误的。因为这两者都是地址,所以可以把它们作为赋给指针变量的值,例如:int *pt;则pt = array或者&array[0]都是合法的。

1.关于地址增加的问题

在C语言里面,对一个指针加1的结果是对该指针增加1个存储单元,注意这里存储单元的含义,解释一下:

int array[4];

int *pt;

pt = array;

数组array的元素类型是int类型。将数组首元素的地址赋值给pt后,pt就指向array第一个元素的地址,假如pt + 1,则会指向array第2个元素的地址,也就是array[1]的地址,但是往后增加了4字节,因为int类型在32位系统下面占用4字节内存。这就是存储单元的含义。也就是pt每增加一次,就往后以4个字节为单位增加。

对于数组来说,地址会增加到下一个元素的地址,而不是下一个字节,道理和指针是一样的,增加的都是它们元素占用的字节大小。

小结一下:

(1).指针的数值就是它所指向的对象的地址(对象的地址通常指的是它们首字节的地址)

(2).对指针加1,等价于对指针的值加上它指向的对象的字节大小(这里指针的值就是所谓的地址,比如0x00000400010....)

(3).在指针前使用*运算符就可以取得这个指针变量保存的地址里面的值(所指向的对象的数值),例如:

int a = 10;

int *pt;

pt = &a;

*pt;

分析一下:我们在变量a里面放一个值10,然后定义了一个指针,把变量a的地址&a赋值给指针pt,这个时候我们就说,pt指向变量a,然后我们使用*符号来获得变量a得值,*pt。同样的,*(&a) == (10).

4.其他的一些小结:

int data[4] = {1, 2, 3, 4};

data + 2 == &date[2];//两者地址相同

*(data + 2) == data[2];//两者值相同

*(data + 2);//表示data的第三个元素的值

*data + 2;//表示第一个元素的值加上2

data + 2是表示元素data[2]的地址;

所以,定义array[n]时候,它的意思是*(array + n),表示寻址到内存里面的array,然后移动n个字节,这里n的含义是array的类型乘以n,然后通过*取出里面的数值。

2.函数、数组、指针

(1)数组作为函数参数的一些知识

假设我们写了一个函数,它的参数是一个数组,那么该怎么写呢?

第一时间可能会想到应该这么写:int Sum(int array[]),这是最直白的写法,还有一种写法就是:int Sum(int *array),这种写法是传递一个指针,我们写一个遍历数组元素,求和的模块代码。

int Sum(int *array, int n)

{

  int index;

  int total = 0;

  for(index  = 0; index < n; index++)

  {

    total += array[index];

  }

  return total;

}

上面的代码中,我们声明时候函数的参数是一个指针,因为数组名就是数组首元素的地址,因此这种写法是可以的,也是比较推荐的,因为它时刻提醒我们,传递进去的是一个地址,此时我们可以传递一个数组也可以传递一个字符串。如果实际参数是一个数组名,那么形式参数必须是与之相匹配的指针,这里的匹配指的是数据类型匹配。

小结一下,下面的四种声明写法是等效的。

int sum(int *ar, int n);

int sum(int *, int);

int sum(int ar[], int n);

int sum(int [], int);

但是作为函数定义时候,参数的名称不可省略,一定要写全,比如:int sum(int array[], int n),或者int sum(int *array, int n);

 (2)指针的部分知识点

需要注意的是,不能对未初始化的指针取值。例如:

int *pt;//未初始化的指针

*pt = 5;

上面的写法,第二行代码把 5存储在pt所指向的地址当中,但是因为pt在声明时候没有被初始化,所以它的值是随机的,也就是说这个指针指向的地方是不确定的,当前我们给这个地址赋值的时候,很可能会覆盖掉里面原有的数据或者代码,会导致程序出现问题。

当创建一个指针时候,系统只是分配了用来存储指针本身的内存空间,并不分配用来存储数据的内存空间。因此在使用指针之前,必须给它赋予一个已经分配的内存地址。比如可以把一个已经存在的变量地址赋值给指针,或者使用malloc()函数来首先分配内存。

原文地址:https://www.cnblogs.com/timemachine213/p/8343603.html