C语言中的数组指针与指针数组:

·数组指针
一、区分

首先我们需要了解什么是数组指针以及什么是指针数组,如下:

int *p[5];
int (*p)[5];
数组指针的意思即为通过指针引用数组,p先和*结合,说明了p是一个指针变量,指向一个大小为5的数组。所以,int (*p)[5]即为一个数组指针。int *p[5]则是一个大小为5且存放整型指针的数组。

二、数组元素的指针

1.定义

指针变量既然可以指向变量,同样的,也能指向数组元素,因此,数组元素的指针就是数组元素的地址。

它的写法为:

int *p=arr;
int *p=&a[0];
这边我们需要再次明确,数组名并不代表整个数组,只是代表数组首元素的地址,因此上面两个语句是一样的。

2.运算

由于指针指向的是一个地址,因此数组指针也同样可以进行相关运算;例如指针的加减可以实现指针指向数组上一个或者下一个元素的功能。这边需要说明,数组指针中进行乘法和除法是没有意义的。

如下图所示:

在定义指针变量的时候需要定义类型,如果指针p指向了一个数组中的一个元素,那么p+1并不是将地址加上1,而是系统判定类型之后加上一个数组元素所占用的字节数(即为p+1*d)。

3.通过指针引用数组元素

代码如下图:

#include<stdio.h>
int main()
{
int a[10]={1,2,3,4,5,6,7,8,9,0};
int *p;
for(p=a ; p<(a+10) ; p++)
{
printf("%d ",*p);
}
printf("\n");
return 0;
}
先让指针p指向a数组的首元素,打印*p(即指向数组的值),然后执行p++,使得p指向下一个元素,直到输出数组的十个元素为止。

三、通过指针引用多维数组

1.多维数组元素的地址

我们以二维数组为例,首先需要明确一点的是二维数组的首元素地址并非一个单个元素,而是首行的地址,如下图:

下面我们列出相关地址的表示方式:

表示形式 含义
a     二维数组名,指向a[0]
a[0], *(a+0), *a 0行0列元素地址
a+1, &a[1] 1行首地址
a[1], *(a+1) a[1][0]的地址
a[1]+2, *(a+1)+2, &a[1][2]
a[1][2]的地址

*(a[1]+2), *(*(a+1)+2), a[1][2] a[1][2]的值
上图都是二维数组中地址的不同表示形式。

2.指向多维数组的指针变量

输出每一个值依然可以像一维数组一样,但这里我们可以介绍一种新的方法:

int main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int (*p)[12];
int i=0;
p=&a;
printf("%d\n",(*p)[11]);
return 0;
}
就像我们前面的例子一样,int(*p)[12]表示定义一个指针变量,它指向一个包含12个整型元素的一堆数组。我们将其设定为12便可以存下整个a数组,当然也可以存一行4个,最后如果输出的话就方便了许多。

四、数组指针作函数参数

下面是几种传参的方式:

void test()
{
int arr[3][5] = {0};
print(arr);
}
void print(int arr[3][5])
{}
void print(int arr[][5])
{}
void print(int **arr)
{}
void print(int (*arr)[5])
{}
我们可以看出第三种方式明显是不行的,这边引用了一个二级指针,但是我们上面提到过数组的地址应该放到数组指针中去。而第四种方法就是我们上面提到过的,而这种方式是可行的。

下面是一个一级指针传参的例子:

#include <stdio.h>
void print(int *p, int sz)
{
int i = 0;
for(i=0; i<sz; i++)
{
printf("%d\n", *(p+i));
}
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9};
int *p = arr;
int sz = sizeof(arr)/sizeof(arr[0]);
print(p, sz);
return 0;
}
·指针数组
一、指针数组

1.定义

int *p[5];
上面使我们刚开始举出的例子,这就是一个最简单的指针数组。因此我们可以得出指针数组的定义。指针数组:一个数组的元素均为指针类型数据,称为指针数组。

假设我们定义一个数组,各个元素指向不同的字符串,如下图:

上图所示,我们定义一个指针数组arr,然后把各字符串的地址赋给各个元素,即arr[0]和arr[1]。

通过一个简单的函数就可以进行输出了。

二、指向指针数据的指针

首先我们可以定义一个指向指针数据的指针变量:

char **p;
为了方便我们理解,其实**p也就等于*(*p)。*p表示p为一个指针变量,前面的*表示*p指向的是char *类型的数据。换一句话来说,如果引用*p,就是得到p所指向的值,如果拿上面的例子来说就是字符串"Hello"和"World"。

我们可以通过下面的代码来实现:

int main()
{
char *arr[]={"Hello","World"};
char **p;
int i;
for(i=0; i<2; i++)
{
p=arr+i;
printf("%s ",*p);
}
return 0;
}
参考博文:

指针数组与数组指针详解:

https://blog.csdn.net/men_wen/article/details/52694069

C语言指针详解(经典,非常详细)

https://blog.csdn.net/constantin_/article/details/79575638

C语言数组指针的更多相关文章

  1. c语言——数组指针和通过指针引用数组元素的方法总结

    1.数组指针:即指向数组的指针 那么, 如何声明一个数组指针呢?int (* p)[10]; /*括号是必须写的,不然就是指针数组:10是数组的大小*/1拓展:有指针类型元素的数组称为指针数组. 2. ...

  2. C语言-数组指针与指针数组

    1.思考 下面这些声明合法吗? int array[5]; int matrix[3][3]; int * pa = array; int * pm = matrix; 问题: array代表数组首元 ...

  3. C语言数组指针(指向数组的指针)

    注意:数组指针的定义,与指针数组的区别 转载:http://c.biancheng.net/cpp/biancheng/view/162.html 指向多维数组元素的指针变量 ① 指向数组元素的指针变 ...

  4. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  5. C语言 数组做函数参数退化为指针的技术推演

    //数组做函数参数退化为指针的技术推演 #include<stdio.h> #include<stdlib.h> #include<string.h> //一维数组 ...

  6. C语言数组和指针的理解_在取地址运算上的操作_指针加减操作_a 和&a 的区别

    1.一个实例+理论分析 在了解数组和指针的访问方式前提下,下面再看这个例子: main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); pr ...

  7. c语言指针数组与数组指针

    一.指针数组和数组指针的内存布局初学者总是分不出指针数组与数组指针的区别.其实很好理解:指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定.它是“储存指针的数组”的简称.数 ...

  8. C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

    原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | I ...

  9. C语言 > 数组和指针

    C语言 数组和指针 const: 关于指针和const需要注意一些规则.首先,把const数据或非const数据的地址初始化为指向const的指针或为其赋值是合法的. 然而,只能把非const数据的地 ...

随机推荐

  1. org.apache.hadoop.mapreduce.lib.input.InvalidInputException: Input path does not exist: file:/input

    原我是这样写的 //输入数据所在的文件目录 FileInputFormat.addInputPath(job, new Path("/input/")); //mapreduce执 ...

  2. selenium选择器_css属性选择器

    搜索 <button class="btn-search tb-bg" type="submit" data-spm-click="gostr= ...

  3. jvm回收器回收过程一:CMS和 G1的初认知(持续更新中)

    CMS:介绍: 1.CMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间的垃圾回收器.对于要求服务器响应速度的应用上,这种垃圾回收器非常适合. 在启动JVM参 ...

  4. [poj P2976] Dropping tests

    [poj P2976] Dropping tests Time Limit: 1000MS  Memory Limit: 65536K Description In a certain course, ...

  5. Harbor使用 -- 修改80端口

    在公网上,一般情况下都不暴露默认端口,避免被攻击! 以下修改harbor的默认80端口为其他端口! 我这里示例修改为1180端口! 注意:以下步骤都是在harbor目录下操作!!! 1.修改docke ...

  6. python dpkt SSL 流tcp payload(从三次握手开始到application data)和证书提取

    # coding: utf-8 #!/usr/bin/env python from __future__ import absolute_import from __future__ import ...

  7. centos 7 安装iptables防火墙

    firewalle: 开启6379端口和16379端口 [root@localhost ~]# firewall-cmd --zone=public --add-port=6379/tcp --per ...

  8. makefile中的wildcard 、patsubst、

    在Makefile规则中,通配符会被自动展开.但在变量的定义和函数引用时,通配符将失效. 这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTE ...

  9. elinks快捷方式

    突然有兴趣看看Linux下的字符模式的浏览器,搜了下有好几个,在Ubuntu里“添加/删除”里找到一个,叫Elinks,安装,然后在终端运行elinks,试用了一下,不错,使用方法也挺简单的,支持多标 ...

  10. 老司机浅谈linux系统学习技巧

    Linux起源于20世纪70年代,是一种优秀的操作系统系统.初次接触到linux这个系统是在大学期间,这样才发现除了windows外的另外一个有趣系统.开始抱着好奇的心态去了解,随着深入学习,笔者被它 ...