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]这三个数据的数据类型

  1. a是数组名,是指向数组第一个元素的指针,毫无疑问,在这里,数组第一个元素的数据类型是int所以a的数据类型是就是int*。
  2. &a是对一个一维数组取地址,得出来的是指向数组的指针(在这里是pointer to array of int), 也就是int(*)[5]。
  3. &a[0]就很简单,首先a[0]得到的是一个整形数int,然后对它取地址,所以它的数据类型就是int*。

知道了数据类型,那么对指针运算看起来就清晰多了!

先看看通过强制类型转换的那部分代码,它会输出什么数字呢?

答案是5! 通过刚才对数据类型的总结可以知道,&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}};
/*
?? = a; // int (*b)[3] = a;
?? = 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]这几者的数据类型:

注意上面加粗了的文字,数组名是指向数组第一个元素的指针!

  1. 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]
  2. 再来看看&a,在一维数组的时候说了,对一个数组名取地址得出来的是指向数组的指针,所以&a的数据类型 就是int (*)[3][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] = a;
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)个字节。

所以对数组指针进行加减运算,最重要的是知道它的步长,而步长又是由数据类型决定的!

  • 指针的值是一个数组的地址
    int ( * pa )[5];
    pa++;pa往后移动20个字节(5*4)

    对比,数组中的元素是指针(int*)
    int *pa[5];
    pa++;pa往后移动4个字节

时间: 2024-11-08 20:20:47

C语言指针一篇中的答案的相关文章

C语言指针—————第二篇:指向另一指针的指针

本文转自 : http://c.biancheng.net/cpp/html/495.html  原文存在部分问题,现在已经修改,并重新发出来 一.回顾指针概念 早在本书第贰篇中我就对指针的实质进行了阐述.今天我们又要学习一个叫做“指向另一指针地址”的指针.让我们先回顾一下指针的概念吧!当我们程序如下声明变量:   short int i;   char a;   short int * pi;程序会在内存某地址空间上为各变量开辟空间,如下图所示: 图中所示中可看出:   i 变量在内存地址5的

C语言 指针基础篇 数组,函数与指针的运用 2 14

下面看看如何在函数中运用指针吧 下面是往函数传入指针的简单操作,不是传入数组的.判断一个a是否大于b是的话给,是的话对其进行操作,不是的话就直接返回. 1 #include <stdio.h> 2 int main(){ 3 int num1,num2,*p1,*p2; 4 p1 = &num1,p2=&num2; 5 scanf("%d%d",&num1,&num2); 6 7 int fun(int *n1,int *n2); //我们在

彻底搞定C语言指针详解

1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧! 先来理解理解内存空间吧!请看下图: 内存地址→ 6 7 8 9 10 11 12 13 ----------------------------------------------------------------- ... | | | | | | | |.. ------------------------------- ---------------------------

彻底搞定C语言指针,初学者必备

1.语言中变量的实质 要理解C指针,我认为一定要理解C中“变量”的存储实质, 所以我就从“变量”这个东西开始讲起吧! 先来理解理解内存空间吧!请看下图: 内存地址→ 6 7 8 9 10 11 12 13 ----------------------------------------------------------------- ... | | | | | | | |.. ------------------------------- ---------------------------

程序设计基石与实践之C语言指针和数组基础

英文出处:Dennis Kubes:  <Basics of Pointers and Arrays in C>. 关于C语言中指针和数组的争论就像是一场恶战.一方面,有些人觉得,所有人都必须承认指针与数组是不同的.而另一些人则认为数组被当成指针来处理,因此它们不应该有什么区别.这种现象让人迷惑.然而,这两种说法其实都是正确的. 数组不是指针,指针也不能说是数组.在C语言中,指针仅在内存中代表一个地址,而数组是许多连续的内存块,多个类型相似的元素存储在其中.更深入的解释,请参考我之前的博文&l

[转]C 语言指针的使用

第一章 指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址. 要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的 类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区.让 我们分别说明. 先声明几个指针放着做例子: 例一: (1)int *ptr; (2)char *ptr; (3)int **ptr; (4)int (*ptr)[3]; (5)int *(*ptr)[4]; 如果看不懂后几个例子的话,请参阅我前段时间贴出的文?lt;<如何

c语言指针学习

前言 近期俄罗斯的陨石.四月的血月.五月北京的飞雪以及天朝各种血腥和混乱,给人一种不详的预感.佛祖说的末法时期,五浊恶世 ,十恶之世,人再无心法约束,道德沦丧,和现在正好吻合.尤其是在天朝,空气,水,食品,你能告诉还有没有问题的吗?不知大难至,世人依旧忙.祸福相依,危中有机.那些高级生命,出于慈悲,会救渡我们,但是你要去思考,去发现机缘. 最近较闲,没事就学点基础知识,整天在上层晃,感觉晕的厉害,接地气.关于指针我上学的时候学过一点,我的老师说"指针很难呢",当时以为这老师挺谦虚的.后

C语言指针总结

C语言中的精华是什么,答曰指针,这也是C语言中唯一的难点.C是对底层操作非常方便的语言,而底层操作中用到最多的就是指针,以后从事嵌入式开发的朋友们,指针将陪伴我们终身.本文将从八个常见的方面来透视C语言中的指针,当然,还有其他没有具体提到的方面,像指针表达式.指针安全等问题,以后有机会我再慢慢补充.还是那句老话,重要的是实践,多写代码,才是学好C语言的关键. 1.指针类型分析分析指针,可以从变量名处起,根据运算符优先级结合,一步一步分析.int p; //这是一个普通的整型变量int *p; /

C语言:指针详解

今日有同学跟我反映,在学习指针的时候,有点懵懵哒,对于初学者来说,这才是应有的赶脚. 好了,废话就不过多的叙述了,我来给大家分析下指针到底是怎么一回事,有说不对的地方,欢迎大家指正,有些是引用,有些是原创,只要能让你明白一点点,也算我功夫没白费 说到指针,先说说地址,看一段小程序 #include "stdio.h" int main() { int a = 10; int *p = &a; printf("%p\n", p); //0x7fff8b6a37