C语言中与指针相关问题——论数组名和数组名取地址的关系

这是由一道面试题联想到的一些问题,这里自己给做个小总结!

首先看看这道面试题:

#include <stdio.h>
int main() {
    int a[5] = { 1, 2, 3, 4, 5 };
    int *pi = &a + 1;

    printf("%d, %d\n", *(a + 1), *(pi - 1));
    return 0;
}

答案是2, 5。至于是为什么,我后面说一下我自己的理解。

这里有个要注意的地方,以上代码在CodeBlock中会有个警告,但是在VS2013中有个错误提示,错误如下:”int()[5]类型的值不能用于初始化”int“类型的实体。当然,这里我们可以进行强制类型转换,那么这个错误提示就会消失。修改后的代码如下:

#include <stdio.h>
int main() {
    int a[5] = { 1, 2, 3, 4, 5 };
    int *pi = (int *)(&a + 1);

    printf("%d, %d\n", *(a + 1), *(pi - 1));
    return 0;
}

这个时候,再编译运行就得到了我们的正确答案2, 5。



我个人对于结果的理解分析:变量a指向的整个数组的首地址,那么变量a每次加1就移动4个字节(相当于从指向第1个数位置移动到指向第2个数);对变量a再进行取地址操作,那么&a每次加1就移动4*5个字节(相当于从指向当前数组首地址位置移动到指向下一个数组首地址位置)。大概示意图如下:


对这道题目进行延伸想到的

#include <stdio.h>
int main() {
    //a是一个二维数组
    int a[2][3];
    /*  1、a的类型是int(*)[2][3],a的值是指向数组第1个元素地址。
    **  2、&a的类型是int*, &a的值是指向整个数组的首地址。
    **  3、a的字节数是4*6, &a的字节数是4。
    */
    printf("a = %x, &a = %x\n", a, &a);
    printf("sizeof(a) = %d, sizeof(&a) = %d\n", sizeof(a), sizeof(&a));
    printf("a + 1 = %x, &a + 1 = %x\n", a + 1, &a + 1);
    /*  1、a[0]的类型是int(*)[3], a[0]的值是指向数组第1行元素第1个元素的地址。
    **  2、&a[0]的类型是int*, &a[0]的值是指向数组第1行整行元素的首地址。
    **  3、a[0]的字节数是4*3, &a[0]的字节数是4。
    */
    printf("a[0] = %x, &a[0] = %x\n", a[0], &a[0]);
    printf("sizeof(a[0]) = %d, sizeof(&a[0]) = %d\n", sizeof(a[0]), sizeof(&a[0]));
    printf("a[0]+1 = %x, &a[0] + 1 = %x\n", a[0] + 1, &a[0] + 1);
}

运行结果如下:

从结果我们可以看到,a,&a,a[0],&a[0]地址值都是一样的,不过由于变量的类型不一样,所以每次移动的值也一样。

时间: 2024-08-03 17:11:40

C语言中与指针相关问题——论数组名和数组名取地址的关系的相关文章

如何理解c语言中得指针

最近有学习了c语言中得指针知识,脑袋都大了,迷迷糊糊理解了一半,由自己查了下资料,跟大家分享下c语言中指针的基本知识吧: 1.指针是一个地址,指向的是个类型. 2:指针指向的是地址,地址指向的是内容. 我们需要一个变量,来存储地址,这个变量的值是地址,但是我们可以通过修改变量的值,来不断的改变地址,但是,我们如果需要改变该个地址的值的话,就需要,对地址的值进行修改,而不改变地址. int a = 10: int *p : p = &a: *p =11: a=? 这里我们看到,p 是一个变量,我们

【ZZ】C 语言中的指针和内存泄漏 &amp; 编写高效的C程序与C代码优化

C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 编写高效的C程序与C代码优化 http://www.cnblogs.com/archimedes/p/writing-efficient-c-and-code-optimization.html

汇编语言的寻址方式与C语言中的指针是一个东西。

汇编语言的寻址方式与C语言中的指针是类似的! 汇编语言的寻址方式与C语言中的指针:寻找数据的方法. 指针就是存了 变量的地址,寻址方式就是得到保存变量的地址. 当你学了汇编语言,你就知道为什么C语言有函数指针,为什么函数要以return 结尾.为什么main()函数为程序的入口. 给我的感觉就是C语言是汇编语言的进化版本.因为C语言处处都有着汇编语言的影子. 一个小小的建议:先学习汇编语言.自学书籍是 清华大学 王爽的 汇编语言.之后,学习C语言,自学书籍,我还真不好推荐,我用的是C语言入门经典

C语言中的指针与数组

1.指针与数组 1)指针与一维数组 i.数组指针(指向数组元素的指针) 类型  *指针变量名: 指针定义完成后要初始化(不想让指向任何内容,=0,=NULL) int a[10]; int *p = &a[0];   // &a[0] == a int *p1 = a; ii.用数组的指针访问数组元素 偏移:指针变量的偏移 p1 = p1+1;    //向下偏移1个一个数组元素 p1++;   //p1中存放的还是地址 .... 如果用指针访问第i个元素 p1+i 取出pi指向的元素的值

【C语言学习】指针再学习(二)之数组的指针

★一维数组 一个整型数据为4个字节.4个字节就是32位,即可以表示2^32个数字 在程序中定义一个数组a[5] = {1,2,3,4,5}; 那么a[0]的地址就是0x00000000,数组名a是数组首元素的地址,a的地址也是0x00000000.a+1则表示的地址是0x00000004,而不是0x00000001.因为1这个值,根据前面的指针a所指向的类型的长度来调整自己的长度.也就是说如果a是指向整型的指针,那么后面加的1也表示4个字节,如果a是指向字符型的指针,那么后面加的1表示1个字节.

C 语言中的指针和内存泄漏

引言 对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具. 本文将与您分享开发人员在开始使用指针来编程前应该知道的秘密.本文内容包括: 导致内存破坏的指针操作类型 在使用动态内存分配时必须考虑的检查点 导致内存泄漏的场景 如果您预先知道什么地方可能出错,那么您就能够小

【转】C 语言中的指针和内存泄漏

避免陷阱 级别: 中级 Manish Virmani ([email protected]), 高级软件工程师, IBM 2006 年 10 月 26 日 在使用 C 语言时,您是否对花时间调试指针和内存泄漏问题感到厌倦?如果是这样,那么本文就适合您.您将了解可能导致内存破坏的指针操作类型,您还将研究一些场景,了解要在使用动态内存分配时考虑什么问题. 引言 对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试

C语言中的指针和内存泄漏

在使用 C 语言时,您是否对花时间调试指针和内存泄漏问题感到厌倦?如果是这样,那么本文就适合您.您将了解可能导致内存破坏的指针操作类型,您还将研究一些场景,了解要在使用动态内存分配时考虑什么问题. 引言 对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是一旦您了解了指针及其关联内存操作的基础,它们就是您在 C 语言中拥有的最强大工具. 本文将与您

【C】C语言中文件操作相关内容

1. 文件和流的关系 C将每个文件简单地作为顺序字节流.每个文件用文件结束符结束,或者在特定字节数的地方结束,这个特定的字节数可以存储在系统维护的管理数据结构中.当打开文件时,就建立了和文件的关系. 在开始执行程序的时候,将自动打开3个文件和相关的流:标准输入流.标准输出流和标准错误.流提供了文件和程序的通信通道.打开一个文件将返回指向FILE结构(在stdio.h中定义)的指针,它包含用于处理文件的信息,也就是说,这个结构包含文件描述符.文件描述符是操作系统数组(打开文件列表的索引).每个数组