浅谈C中的指针和数组(五)
前面写了一些C指针和数组的一些知识,但是还有一些很重要的知识没有交代,这里做一个补充。
首先看一下,普通变量(指针也是变量)和数组名查看地址的方式是不同的。
查看数组变量的地址,不需要使用 & 。C,C++语言中,对数组变量的操作,就相当于直接对该数组变量的地址的操作。
#include<stdio.h>
#include<stdlib.h> int main(void)
{ int arr[]={,,};
int a = ;
int *p = &a;
printf("%p\n", &a);
printf("%p\n", &p);
printf("%p\n", arr);
printf("%p\n", p); system("pause");
return ;
}
执行的结果:

可以看出,对于普通的变量(包括指针变量),想查看其地址,都要加上&符号,表示打印其编译器符号表中的对应于变量符号的地址。否则打印的就是符号表中对应的地址的内存单元中存放的数据。
但是数组的名字不用加&符号,直接打印的就是符号表中的地址。
二维数组
实际上C语言没有多维数组,有的只是数组的数组。
指针与多维数组
(主要指二维数组)
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
在说之前,说明一件事,数组的地址直接是在编译的时候写在编译器的符号表中的,不需要想指针变量那样间接取址。符号表的表项中有一项是类型,地址的加减的调整量就是根据这个类型确定调整量大小的。
数组名自它定义时起就确定下来,不能通过赋值的方式使该数组名指向另外一个数组。
换个角度看世界:
如首行一样,将首行视为一个元素,一个特殊的元素,这个“特殊的”元素是一个一维数组。那么这个二维数组是由是由三个“特殊的”元素组成的一个“特殊的”一维数组。
a是这个“特殊的”一维数组的名称,也就是首地址,也就是第一个元素的地址,也就是第一行的首地址,是指首行一整行,并不是指某个具体元素。那么我们称之为“行指针”。同理:a+0,a+1,a+2,都是行指针。
结论:
| 表示形式 | 含义 | 指针类型 | 
| a或者a+0 | 指向第0行 | 行指针 | 
| a+1 | 指向第1行 | 行指针 | 
| a+2 | 指向第2行 | 行指针 
 | 
接下来,我们来放大观看首行,首行的元素分别是:a[0][0],a[0][1],a[0][2],a[0][3]。将其看作一个独立的一维数组,那么 a[0]就是这个数组的名称,也就是这个数组的首地址,也就是第一个元素的地址,也就是a[0]+0。a[0]和a[0]+0都是指具体的元素,那么我们称之为“列指针”。
结论:(第0行视为一维数组)
| 表示形式 | 含义 | 指针类型 | 
| a[0] | 是一维数组的名称,也是它的首地址,而且是第1个元素的地址(a[0]+0) | 列指针 | 
| a[0]+1 | 第0行,第2个元素的地址 | 列指针 | 
| a[0]+2 | 第0行,第3个元素的地址 | 列指针 
 | 
两个重要概念:行指针和列指针。
行指针:指的是一整行,不指向具体元素。
列指针:指的是一行中某个具体元素。
可以将列指针理解为行指针的具体元素,行指针理解为列指针的地址。
那么两个概念之间的具体转换是:
*行指针----列指针(修改符号表中的类型,修改指向的内存空间的大小)
&列指针----行指针
从上面看来,一个指针变量(暂且把数组名当做指针,其实不是)包括两个方面:指向的地址和指针的类型。
根据以上转换公式:
| 行指针 | 转换成:列指针 | 列指针等价表示 | 内容 | 内容等价表示 | 含义 | 
| a或a+0 | *a | a[0] | *a[0] | *(*a) | a[0][0] | 
| a+1 | *(a+1) | a[1] | *a[1] | *(*(a+1)) | a[1][0] | 
| a+2 | *(a+2) | a[2] | *a[2] | *(*(a+2)) | a[2][0] | 
对于元素a[1][2],其地址用列指针表示为a[1]+2,等价表示为*(a+1)+2,那么内容是*(*(a+1)+2);
| 列指针 | 行指针 | 等价表示 | 含义 | 
| a[0] | &a[0] | &a或&(a+0) | 第0行 | 
| a[1] | &a[1] | &(a+1) | 第1行 | 
| a[2] | &a[2] | &(a+2) | 第2行 
 | 
示例1:用列指针输出二维数组。
#include <stdio.h> void main()
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int *p= a[0]; // 列指针的定义法 for(; p < a[0] + 12; p++)//这里要知道数组是按行还是按列存储的
{
printf("%d ",*p);
} return;
}
示例2:用行指针输出整个二维数组。
#include <stdio.h> void main()
{
int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int (*p)[4]= &a[0]; // 行指针定义法或者int (*p)[4]= a; int i, j;
for(i = 0; i < 3; i++)
{
for(j = 0; j < 4; j++)
{
printf("%d ",*(*(p + i) + j));
}
} return;
}
看一下sizeof和&符号对二维数组的操作:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[2][3] = {{1,2,3},{4,5,6}};
//这里的a代表行指针,指向数组第一行
//a[0]代表列指针,指向第0行的首个元素的地址
//sizeof和&两个操作会使数组变大
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0]));
system("pause"); return 0;
}
执行结果:

产生这种结果的原因在前面指针和数组名的相同点(它们都能以数组或者下标的形式访问)中做了说明,这属于那两个特例,就是说在sizeof和&操作符的时候,大小是不一样的,操作形式也会发生变化。
指针和数组的内容到这里全部笔记做完了,最后补充一点点C语言的定义和声明的部分:

对二维数组的访问,看到其实没有多次的访问内存取地址:

浅谈C中的指针和数组(五)的更多相关文章
- 浅谈C中的指针和数组(一)
		本文转载地址:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242138.html 在原文的基础上加入自己的想法作为修改. 指针是C/C ... 
- 浅谈C中的指针和数组(二)
		原文转载地址:http://see.xidian.edu.cn/cpp/html/475.html 在原文的基础上增加自己的想法作为修改 很多初学者弄不清指针和数组到底有什么样的关系.我现在就告诉你: ... 
- 浅谈C中的指针和数组(三)
		上一个博客我们得到了一个结论: 指针和数组根本就是两个完全不一样的东西.只是它们都可以“以指针形式”或“以下标形式”进行访问.一个是完全的匿名访问,一个是典型的具名+匿名访问.一定要注意的是这个“以X ... 
- 浅谈C中的指针和数组(四)
		原文转载地址:http://see.xidian.edu.cn/cpp/html/476.html 在原文的基础上增加自己的思想作为自己的修改 指针数组和数组指针的内存布局 初学者总是分不出指针数组与 ... 
- 浅谈C中的指针和数组(七)
		现在到揭露数组名本质的时候了,先给出三个结论: (1)数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组: (2)数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量: ( ... 
- 浅谈C中的指针和数组(六)
		数组和指针,原本不想在写了,觉得这部分差不多了,但是自己在写程序的时候还是发现了一个错误.首先说一下我的要求: 给一个函数传递一个二维数组,然后我想在这个函数里面计算这个数组的行数. 写个类似的错误D ... 
- 浅谈C语言 extern 指针与数组
		/* * d.c * * Created on: Nov 15, 2011 * Author: root */ #include "apue.h" int a[] = {3,2}; ... 
- 转: 浅谈C/C++中的指针和数组(二)
		转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242419.html 浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组 ... 
- 转:浅谈C/C++中的指针和数组(一)
		再次读的时候实践了一下代码,结果和原文不一致 error C2372: 'p' : redefinition; different types of indirection 不同类型的间接寻址 /// ... 
随机推荐
- Windowsclient开发简单介绍(四)
			在上一篇文章里,我简单扼要的给大家介绍了一下GDI的基础知识,包含DC,HDC.GDI对象等等,总的来说都是些偏理论的知识,属于概念的范畴. 今天这篇文章里,我就要正式開始有点实际的东 ... 
- Error in invoking target 'agent nmhs' of makefile
			安装Oracle11g报错:Error in invoking target 'agent nmhs' of makefile 解决方法:cd $ORACLE_HOME/sysman/libvi i ... 
- 代码生成引擎之T4模版
			在学校三年.公司里呆了快一年了,作用ASP.NET开发的我,居然从来没听过T4模版,公司里也没有人使用,它就是这样不为世人所熟知,却又默默的奉献着!这...........tm还是我吗?什么时候会说这 ... 
- asp.net文件下载
			protected void btn_Down(object sender, EventArgs e) { string filePath = Server.MapPath("/TradeL ... 
- Android Studio无法关联Api23源码-提示Souces for android api 23 platform not found
			最近升级了As,然后忽然就关联不上源码了,很不方便,找个Activity的源码都只有outline没有解释,还提示这个错误: Decompiled .class file, bytecode vers ... 
- (转)OpenGL中位图的操作(glReadPixels,glDrawPixels和glCopyPixels应用举例)
			(一)BMP文件格式简单介绍 BMP文件是一种像素文件,它保存了一幅图象中所有的像素.这种文件格式可以保存单色位图.16色或256色索引模式像素图.24位真彩色图象,每种模式种单一像素的大小分别为1/ ... 
- bootstrap简章
			系统整理一遍bootstrap 的东西 1/ 设置页面为H5文档类型 <!DOCTYPE html> <html lang="zh-CN"> ... &l ... 
- 初学swift笔记-数组、字典、元组(三)
			数组的使用.字典的使用.元组的使用 import Foundation //1.定义数组 //集合数据 数组.字典 ,,,]//常用定义 ,,,]//常用定义 ,,,]//范型定义 ,,,] arr_ ... 
- Google TensorFlow深度学习笔记
			Google Deep Learning Notes Google 深度学习笔记 由于谷歌机器学习教程更新太慢,所以一边学习Deep Learning教程,经常总结是个好习惯,笔记目录奉上. Gith ... 
- bash快捷建-光标移到行首、行尾等
			转自:http://digdeeply.org/archives/12131599.html ctrl键组合ctrl+a:光标移到行首.ctrl+b:光标左移一个字母ctrl+c:杀死当前进程.ctr ... 
