C语言打印输出指针数组
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言打印输出指针数组相关的知识,希望对你有一定的参考价值。
书上的两个例子,一个是
int main (int argc,char *argv[])
int m;
for(m=1;m<argc;++m)
printf("%s\n",argv[m]);
int main (int argc,char *argv[])
while(*argv!=NULL)
printf("%s\n",*argv++);
为什么第二个打印需要加*,请大神给解释一下
1、指针的本质是一个与地址相关的复合类型,它的值是数据存放的位置(地址);数组的本质则是一系列的变量。
2、数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。指针可以随时指向任意类型的内存块,它的特征是"可变",所以我们常用指针来操作动态内存。
3、当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。
因为第三条,当把数组名作为函数的形参进行传递时,该效果等同于传递一个同类型的指针。直接在程序当中调用 函数名(数组名)即可。
例程:
#include
int a[]=1,2,3,4,5,6;
void print(int a[])//数组指针作为形参
for(i=0;i<6;i++) printf("%d ",a[i]);//输出数组
int main()
print(a);//传入数组名
return 0;
参考技术B *argv[] 的结构大概是这样的 "abc","def",argv指向结构的开始位置。argv+1 指向“def”起始位置 参考技术C *argv指针,
argv[]数组,
数组可以用指针来表示 参考技术D 因为是指针 加*表示取内容
一个关于C语言的指针与二维数组的问题
自己写了段简短的代码来验证数组地址,数组内容和指针之间的关系。。
如下:
#include<stdio.h>
void main()
int zippo[4][3]= 2,4,1, 6,8,1, 1,3,1, 5,7,1;
printf(" zippo=%p, zippo+1=%p \n", zippo , zippo+1 );
printf(" *zippo=%p, *zippo+1=%p\n" , *zippo, *zippo+1);
输出结果如下:
zippo=0012FF50, zippo+1=0012FF5C
*zippo=0012FF50, *zippo+1=0012FF54
Press any key to continue
对于第一行的输出结果我有点不理解。我把zippo和zippo+1都理解成一个二级指针,那么它们分别指向一个一级指针,而一个指针本身所占的内存是4个字节,那zippo和zippo+1的地址之差不应该是一个指针所占有的内存值,也就是4吗?但是我从结果推回去相差的是12,也就是说相差了第一组数据2,4,1三个整形常量的内存值……哪位高人指点下迷津?
我要的不是答案……我想知道我那么想怎么错了。。。我的意思是,按照程序的运行结果,那不是把指针本身的地址和指针所指向的对象的地址等同起来了么?二级指针指向的应该是一级指针的地址呀,也就是4个字节……那二级指针加1为什么地址不是加了4呢?……
呵呵,厉害!也就是说应该把数组的首地址理解成一种特殊的地址类型吧,即zippo的长度是4*3*sizeof(int),*(zippo+1)的长度是3*sizeof(int),而zippo+1的长度才应该是一个普通地址长度,即4
这样定义的原因是两者本身的语义不同。引用一个表示数组的标识符(数组名)具有两重含义,一是指整个数组,二是指指向数组首个元素(而不是整个数组)的指针。具体取两种含义是上下文相关的。在定义数组、作为sizeof或一元&操作符的操作数这些左值语义上下文中,数组名表示第一种含义;其它情况下,取第二种含义。因此,C语言中在某些场合(例如参数传递)数组可以丢失长度信息,退化为对应的指针(这里的退化是指隐式地类型转换,保持数组元素和指针指向的对象的类型相同)。(如果不考虑类型,两种含义得到的值都是相等的,即数组首个元素的第一个字节在存储器地址空间中对应的整数值——地址(值),因此编译器一般以此实现数组,同时在目标代码中完全不保留数组的类型信息。)但反之无法实现。
作为以下内容的前提,LZ必须明确,被一个指针指向的是对象——即具有确定地址的一个的实体(作为一个表达式,可以是左值),而不是作为一种整数的“地址”(尽管指针的值等于被指向对象的地址)。要点在于,指针是有类型(而且和被指向的类型对应)的,类型会影响操作的具体行为。
C语言的核心语言特性没有直接支持多维数组,所谓的多维数组,只不过是元素为数组的数组。由于元素类型是数组类型的必要组成部分,因此指针类型元素的数组和一维数组类型元素的数组(通常所说的“二维数组”)是不同的(所以不是像LS说的——你“可以”,而是“必须”把二维数组看成数组的数组)。而二维数组更不是二级指针。二级指针指向的是一级指针,它的值是一级指针的地址——由于是两个不同的对象(左值),二级指针的地址和这个值自然不同(如果因为指向自身而导致值相同,则至少需要一次显式类型转换,因为一级和二级指针之间不会隐式地转换);而因为以上的数组语义的关系,二维数组可以退化成不同的指针,类型不同,但地址值相同。结合LZ的例子来讲,二维数组zippo可以退化为&zippo[0](zippo[0]是一个一维数组,&zippo[0]是指向它的指针),或者继续退化为&zippo[0][0](指向一维数组zippo[0]的首个元素zippo[0][0]的指针)这两个指针右值,而三者的值都是同一个地址。
然后是“+”的问题。这里又有一个陷阱:数组作为additivate operator(二元+和-)算术操作的操作数,它的类型会影响+和-的具体行为,满足“下标移动”的语义。从实现上来说,同指针+、-操作一样,对于一个整数,地址值的改变值是除了指针/数组外另一个整数操作数乘以sizeof(被指向的类型或元素类型)。例如,i是一个正整数,zippo是表示一个数组或者指针标识符,那么zippo + i按下标移动应该等价于&zippo[i],从实现上来看相当于(zippo的类型)((intptr_t)zippo + (intptr_t)(sizeof(*zippo) * i))(其中intptr_t是标准库定义的和在该平台下指针大小相同的整数类型)。LZ的问题中,如果zippo是二级指针,那么zippo和zippo+1的地址之差确实应该是一个(一级)指针所占存储器空间的大小(等于sizeof(intptr_t),32位平台也就是4)。但是这里zippo是二维数组,那么sizeof(*zippo)等于它的元素——一维数组的sizeof值,自然可以不是4。
====
[原创回答团]
参考资料:原创
参考技术A #include <stdio.h>int main()
int array[4][3];
int *p1 = array[0];/*一级指针*/
int (*p2)[3] = array;/*二级指针*/
printf("%d,%d\n", array,array+1);
printf("%d,%d\n", p1,p1+1);
printf("%d,%d\n", p2,p2+1);
return 0;
//int array[4][3];可以看做int (*p[4])[3];即一个数组,每个数组元素指向某一个三int元素数组 参考技术B 二维数组啊,当然就是输出这样的结果的啊
zippo是第一行的地址
zippo+1第二行的地址
*zippo第一个元素的地址
*zippo+1第一行第二个也是整个数组第二个元素的地址
绝对是正解 参考技术C zippo是二维指针
所以 zippo+1 则zippo后移一个元素的长度 即 一维数组的长度
int [3] = 4 * 3 = 12 参考技术D 1个n*m二维数组,你可以看成是n个长度为m的一维数组组成的。
假设数组a[100][100].
a[0]表示的是数组的第零行的首地址,也即是整个二维数组的首地址。
a[1]表示的是数组的第一行的首地址。
你那程序里的加1就已经是到数组的下一行了,肯定地址需要加上整一行打大小了。 第5个回答 2010-08-05 zippo的是zippo[0][0],zippo+1 的是zippo[1][0]
以上是关于C语言打印输出指针数组的主要内容,如果未能解决你的问题,请参考以下文章
Arduino指向结构变量的指针和指向结构数组的指针打印输出
C 语言二级指针作为输入 ( 二维数组 | 抽象业务函数 | 二维数组打印函数 | 二维数组排序函数 )