c语言指针关于指针的一些基础问题 但这个(原谅我的爆粗口)傻逼的老师! 已经把我弄晕了。。。。 求大神

问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
C语言指针问题
下面代码为什么第二个数字是5呢?
int a[5] = {1,2,3,4,5};
int *p = (int *)(&a+1);
NSLog(@"%d,%d", *(a+1), *(p-1));
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
&a得出来的是指向数组的指针,所以&a+1其实是以数组的长度为单位来移动的。如果你只是想要得到数组的第二个元素的话,那么就用*(&a[0]+1),因为&a[0]的数据类型是int*。画个图先:
假设有以下数组
int a[5] = {1,2,3,4,5};
int *x = &a+1;
虽然上面的程序可以编译通过,但是,编译器会出警告,因为x和a的类型不匹配,要想把警告去掉,有两种方法
1、通过强制类型转换
int *x = (int *)(&a+1);
print("%d\n",*(x-1));
2、为它寻找合适的类型 &a的类型是int (*)[5]
int (*x)[5] = &a+1;
printf("%d\n",**(x-1));
这里就牵涉到了如何写出适当的数据类型,这在赋值和参数传递中很重要!
所以,首先我得总结一下a,&a和&a[0]这三个数据的数据类型
a是数组名,是指向数组第一个元素的指针,毫无疑问,在这里,数组第一个元素的数据类型是int所以a的数据类型是就是int*。
&a是对一个一维数组取地址,得出来的是指向数组的指针(在这里是pointer to array of int), 也就是int(*)[5]。
&a[0]就很简单,首先a[0]得到的是一个整形数int,然后对它取地址,所以它的数据类型就是int*。
知道了数据类型,那么对指针运算看起来就清晰多了!
先看看通过强制类型转换的那部分代码,它会输出什么数字呢?
通过刚才对数据类型的总结可以知道,&a的数据类型是int (*)[5],所以&a+1其实是已经移动了5*sizeof(int)个字节了
现在指针是指到了数组最后一个元素的后一个元素(图1),也就是说,已经越界了!但是因为x的数据类型其实是int *
所以对于x-1,其实是向左移动了1*sizeof(int)个字节,也就是指向了最后一个元素,所以*(x-1)得出来的
值就是数组的最后一个元素:5
好了,现在再看第二部分,它又会输出什么数字呢?先不说答案,刚才也说了,在这里
x的数据类型是int (*)[5],是一个指向含有5个int元素的一维数组的指针,对它进行加减运算的话就会以
sizeof(int)*5个字节为单位进行移动,所以x-1其实是向左移动了sizeof(int)*5个字节,在我的机器上是移动了
20个字节,也就是回到了数组的第一个元素,所以得出来的答案就是:1
以上是一维数组的,下面我想说说二维数组的情况,有以下一段代码:
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
?? = // int (*b)[3] =
?? = a[0]; // int *c = a[0];
?? = a[0][0] // int d = a[0][0];
?? = &a; // int (*e)[3][3] = &a;
?? &a[0]; // int (*f)[3] = &a[0]
?? &a[0][0]; // int *g = &a[0][0]
还是先看看a,a[0],&a,&a[0],&a[0][0]这几者的数据类型:
注意上面加粗了的文字,数组名是指向数组第一个元素的指针!
a的数据类型是??int *?不是,这句加粗了的文字的核心就是第一个元素这五个字,
a的第一个元素不就是a[0][0]吗?严格来说,不是,a的第一个元素其实是a[0],那么a[0]的数据类型是什么呢?a[0]
是一个包含三个int元素的数组,所以a[0]的类型就和int t[3]中t的类型一样,是int*,既然第一个元素 的数据类型是
int*,那把这个二维数组看成一维数组的话,实际上它就是一个含有三个int*元素的
数组,也就是指针数组,所以a的数据类型就是int (*)[3]
再来看看&a,在一维数组的时候说了,对一个数组名取地址得出来的是指向数组的指针,所以&a的数据类型 就是int (*)[3][3]
&a[0]这个看上去有点蛋疼,但是在上上段文字中也说了,a[0]是一个包含三个int元素的数组,和int t[3]
中的t的数据类型一样,是int*,自然,&a[0]的数据类型就和&t的数据类型一样,也就是int (*)[3]
到这里,二维数组中关于数据类型就写得差不多了,既然知道了数据类型,那么运算起来就可以准确知道指针会移动到哪里!
看看下面这段代码:
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
int (*x)[3] =
int *k = a[0];
int (*y)[3][3] = &a;
int (*q)[3] = &a[0];
int *z = &a[0][0];
printf("%d\n",(*(x+1))[0]);
printf("%d\n",*(k+1));
printf("%d\n",(*(*(y+1)))[0]);
printf("%d\n",(*(q+1))[0]);
printf("%d\n",*(z+1));
int *p = (int *)(y+1);
printf("%d\n",*(p-1));
x的数据类型是int (*)[3],所以,x+1实际上是移动了3*sizeof(int)个字节,如图所示:
k的数据类型是int *,所以,k+1实际上是移动了sizeof(int)个字节。
y的数据类型是int
(*)[3][3],所以y+1实际上是移动了3*3*sizeof(int)个字节,也就是到了数组最后一个
元素的后面的一个元素。如图所示:
q的数据类型是int (*)[3],所以,q+1实际上也是移动了3*sizeof(int)个字节。
z的数据类型是int *,所以z+1实际上是移动了sizeof(int)个字节。
所以对数组指针进行加减运算,最重要的是知道它的步长,而步长又是由数据类型决定的!
同步到新浪微博
分享到微博?
与我们一起探索更多的未知
专业的开发者技术社区,为用户提供多样化的线上知识交流,丰富的线下活动及给力的工作机会
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要举报该,理由是:
扫扫下载 App
SegmentFault
一起探索更多未知解密C语言的指针
> 解密C语言的指针
解密C语言的指针
  作为嵌入式开发的基础语言已经越来越让工程师们知道它的厉害:可以直接操控寄存器,方便CPU的功能设置;可以直接操作物理地址,并进行位的操作进而达到硬件的操作等等。如果你用8位16位单片机进行开发学习,相信使用一些程序技术可以完成设计:循环、选择、位操作、条件判断、数组和程序嵌套等。如果你进行操作系统,关注操作系统的内核(以为例),你就会发现这些是其中的一小部分。对于操作系统来说更多运用到,究其原因,一个很重要的原因就是处理速度快。那么,今天我就把的做个总结。本文引用地址:  第一、 和常数  对于学习过指针的同学都知道,常数是不能直接幅值给指针的,如果想给指针幅常数,需要如下操作:  int num=8;  int *pnum=&  这时我们需要注意,pnum指向8存储的地址,*pnum为该地址存储的数据8。  第二、 指针和数组  指针和数组有着天然的联系,其实数组就是一个连续地址存放着常数,我们看下面一个例子:  int arry[3]={1,3,5};  那么arry就是该数组的首地址,*arry就是该数组首地址存放的数据1,*(arry+1)则为该数组的第二个位置存放的数据3.  从以上分析可以看出:  *arry和arry[1]同样指向该数组的首个元素。  那么可以在进一步延伸,如下:  a 、int *data[3] 为指针数组,数组中每个元素为一个指向int型数据的指针,赋值如下:  int arry[3]={1,3,5};  int *data[3]={arry,arry+1,arry+2};  data[0]为指向arry首地址,*data[0]为该地址存放的数据1。data为data数组的首地址,*data和data[0]都为数组arry的首地址。其实也可以说定义了三个数组 data[0], data[1]和data[2]。  b、int(*data)[3]为一数组指针,为一数组,每个元素为存放一个地址,赋值如下:  int arry[3]={1,3,5};  int (*data)[3]=&  那么*data就为第一个元素的地址,**data就为第一个地址所在的元素1。  看到这里,你是不是已经感受到指针的乐趣了?更有趣的还在下面,喝杯水,继续分析。  第三、 指针与结构体  这个也是一个很有趣的方面,先看一个例子:  struct PERSON  {  char *    }  如果想给*pername幅值,那么可以如下操作:  person.pername=&jack&;//用指针,可以完成赋值  如果结构体定义为  struct PERSON  {  char pername[20];    }  那么person.pername[20]=&jack&是不能通过的,究其原因就是结构体为抽象数据类型,不分配存储单元,所以数组赋值不通过。如果采用指针赋值,那么可以解决这类问题。  第四、 指针与函数  指向函数的指针在操作系统中很常见,现在拿个简单的例子来进行说明:  int print(int a, int b ,char *p)  { printf(&in put number sum is %d,input string is %s\n&,a+b,p);//三个参数,int int和char*  return a+b;}  int main()  {  int (* pprint)(int,int,char *);//定义指向函数print的指针函数*pprint,三个参数,int int和char*  pprint=//给指针函数赋值    c=pprint(3,6,var);  printf(&%d\n&,c);//输出print的return值  }  从上面这个例子中可以看出,一个函数其实就是从一个地址开始的特殊功能程序,其函数名就为该程序的首地址,所以可以这么给指针函数赋值:pprint=//给指针函数赋值  经过以上唠叨,相信你对指针有了更深入的认识,在实际的工作中不仅仅是这么简单的问题,如果你是做纯软件开发,那么效率永远是第一位的,那么,你就要好好的利用指针这个工具了。操作系统文章专题:
linux操作系统文章专题:
c语言相关文章:
linux相关文章:
分享给小伙伴们:
我来说两句……
最新技术贴
微信公众号二
微信公众号一关于C语言指针的一些问题_百度知道
关于C语言指针的一些问题
%d&elsemax=*pb,为什么不能用P我一直不太明白指针在前面声明了。在比较大小的地方,必须带指针符号,后面有的地方要用*p;,pc)max=*pa,有的不要用,max);scanf (&;;system(&quot,max,为什么输入的内容时候不能用*p,c,必须是P,*pb=&b,省略指针符号,*pc=&c,)。 求高手指点main(){%d%d%d&}if (max&%d&else printf (&quot,b, *pa=&a;%d%d%d&quot,pb,pb,pc);;← 就是这个位置 为什么不能写成
scanf (&quot,比如下题;*pc)printf (&quot,*pc);pause&quot,pa
*pa=&a;%d%d%d&quot,*pc){if (*pa&system(&%d&quot,b;else printf (&quot,*pa,*pb=&b,*pc);,*pc)printf (&;pause& scanf (&,max);}if (max&gt,c上面的程序粘贴的时候搞的不完整了 下面是完整的main(){ ← 就是这个位置 为什么不能写成
scanf (&quot,elsemax=*pb,*%d%d%d&);%d&quot,pc),*pb)
这个地方为什么又要必须带*号了max=*,*pc=&c
提问者采纳
当把&a赋给pa时就让pa这个指针变量指向了a的地址开始的时候*pa代表定义了一个指针变量pa,这时用pa和用&a就是一个意思了,输入的时候要用地址输入,而后面那个是变量比较大小不是地址比较,而用*pa就和用a是一个意思了
提问者评价
原来是这样,感谢!
其他类似问题
71人觉得有用
相当于scanf (&quot,*pb=&b;,*pc);elsemax=*%d&
{if (*pa&gt,pb,max), &a,所以pa就是a值的地址main(){%d%d%d&quot, &c);, *pa=&a;),*pc=&c;else printf (&quot,max,b;system(&%d%d%d&quot,指针就是地址;,pa,pc);
前面已经把pa定义为指针类型, &b;;pause&*pb)
*pa是对数据的引用max=*}if (max&*pc)printf (&%d&quot,c; scanf (&quot
为您推荐:
其他2条回答
int*%d%d%d&
&#47声明是必须带 * 号,相当于scanf (&quot,赋值时不用带 * 号int a, &c); 声明为int类型的指针p = &a,就是声明且赋值a的地址 scanf (&quot,这个是合法的;;
// p保存着a的地址int* q = &a,
//%d%d%d& 当然可以两个合在一起写;&#47,pc), &b, &a;
推荐你看一下《c程序与指针》经典著作,不要仅限于看国内的一些教材了没有大师水平
c语言的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁C语言关于指针的一些基础问题_百度知道
C语言关于指针的一些基础问题
使用指针变量做函数参数,编写函数求两个数的订攻斥纪俪慌筹苇船俩大于、小于、等于关系。下面这个程序为什么运行的了 但是 输入4 5 输出却是4&- #include&stdio.h&int main(){ void compare (int*p1,int*p2);int a,b;int*pointer_1,*pointer_2;printf(&please enter 2 numbers:\n&);scanf(&%d,%d&,&a,&b);pointer_1=&a;pointer_2=&b;compare(pointer_1,pointer_2);return 0;}void compare(int*p1,int*p2){if (*p1&*p2){ printf(&%d&%d\n&,*p1,*p2);}else if (*p1&*p2){
printf(&%d&%d\n&,*p2,*p1); } else {
printf(&%d=%d\n&,*p1,*p2); }}
提问者采纳
输入的时候把输入法关掉,或者切换成英语半角输入
哦哦 对 是逗号要用无输入法的状态输入才可以啊 谢谢诶!!!!!!
提问者评价
其他类似问题
为您推荐:
c语言的相关知识
其他4条回答
#include&stdio.h&int main(){ void compare (int*p1,int*p2);int a,b;int*pointer_1,*pointer_2;printf(&please enter 2 numbers:\n&);scanf(&%d,%d&,&a,&b);//这里你指定以4,5这样的方式输入,你输入4 5当然是不行的要输订攻斥纪俪慌筹苇船俩入4,5
4和5用逗号隔开,望采纳pointer_1=&a;pointer_2=&b;compare(pointer_1,pointer_2);return 0;}void compare(int*p1,int*p2){if (*p1&*p2){ printf(&%d&%d\n&,*p1,*p2);}else if (*p1&*p2){
printf(&%d&%d\n&,*p2,*p1); } else {
printf(&%d=%d\n&,*p1,*p2); }}
嗯嗯 逗号不能用输入法输入
我估计是你的输入有问题!scanf(&%d,%d&,&a,&b);看见没?根据你的写法,你输入时是以逗号作为隔开符的!输入时应该是4,5
输入格式4,5就正确了
scanf(&%d %d&,&a,&b);这一句把那个dou'hao去掉,改成这样就ok了~
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 c语言指针详解 的文章

 

随机推荐