/*
 * d.c
 *
 *  Created on: Nov 15, 2011
 *      Author: root
 */
#include "apue.h"
int a[] = {3,2};
void hello()
{
    printf("d.c %d",a);
}
/*
 ============================================================================
 Name        : hello.c
 Author      :
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include "apue.h"
extern void hello();
extern int *a;

int main(void)
{
    hello();
    printf("\n : %d",a);
    return EXIT_SUCCESS;
}

上面的代码的输出为 

d.c 134520856  
: 3

第一行代码是第一个文件d.c输出了int a[];a的内容

第二行代码是第二个文件hello.c输出了extern int *a;指针a的内容

gcc编译的时候,在链接阶段了,hello.o有extern a符号,在d.o中找到,所以extern a 和d.o的a是同一个符号(我认为称他们“指向相同”有歧义)

也可以用图像表示

。数组第一项在内存地址134520856处。

第一个文件d.c将a当成数组来处理,可以按照想象的进行输出,但是

但是第二个文件是把符号a当成指针来操作的(因为 extern int *a), 指针所在的地址是134520856,但是指针的值是3(理解吗?)。

如果将hello.c改成下面这样

#include "apue.h"
extern void hello();
extern int *a;

int main(void)
{
    hello();
    printf("\n : %d",a[1]); // 这里被修改了
    return EXIT_SUCCESS;
}

在main函数中,按照编译器的规矩,a[1]可以被我们这样认为 *(a+1);

因为a等于3,a+1等于4,*(a+1)的意思就是取内存地址为4的字节内容,我不知道地址为4的那个字节里面是什么东西。但是起码不是我们想要的。

 

 转载请注明出处:http://www.cnblogs.com/stonehat/archive/2011/11/15/2250091.html 

二、再看下面的代码。

// file : d.c
#include "apue.h"
int *a;
void hello()
{
    a =(int *) malloc(2);
    a[0]=3;
    a[1]=2;
    printf("d.c %d",a);
}

// file : hello.c

#include "apue.h"
extern void hello();
extern int *a;

int main(void)
{
    hello();
    printf("\n : %d",a);
    return EXIT_SUCCESS;
}

输出结果:

d.c 161968136
: 161968136

我说了实际上 只要是extern a就表示这两个a符号,实际上是同一个符号a,(你可以将两个文件的函数输出&a,就会发现他们的地址是一样的)。

这种情况下的内存分配是这样的。

如果main函数改成这样的,就是输出a[1]的值,

int main(void)
{
    hello();
    printf("\n : %d",a[1]);
    return EXIT_SUCCESS;
}

按照规矩,输出*(a+1),a等于161968136, 加1,就等于161968140(懂?),就会输出2.

 

三、再看一种情况。

// d.c
#include "apue.h"
int *a;
void hello()
{
    a =(int *) malloc(2);
    a[0]=3;
    a[1]=2;
    printf("d.c value:%d\n",a);
    printf("d.c address:%d\n",&a);
}

// hello.c

extern void hello();
extern int a[];

int main(void)
{
    hello();
    printf("hello.c value:%d\n",a);

    printf("hello.c address:%d\n",&a);

    printf("hello.c  a[1]",a[1]);
    return EXIT_SUCCESS;
}

输出结果为:

d.c value:160223240
d.c address:134520864
hello.c value:134520864
hello.c address:134520864
hello.c a[1]

内存分布图为:

在hello.c中,a被当成int a[];

a的值为160223240, *(a+1),就能够访问到2.

 转载请注明出处:http://www.cnblogs.com/stonehat/archive/2011/11/15/2250091.html 

浅谈C语言 extern 指针与数组的更多相关文章

  1. 浅谈C中的指针和数组(一)

    本文转载地址:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242138.html 在原文的基础上加入自己的想法作为修改. 指针是C/C ...

  2. 浅谈C中的指针和数组(五)

    前面写了一些C指针和数组的一些知识,但是还有一些很重要的知识没有交代,这里做一个补充. 首先看一下,普通变量(指针也是变量)和数组名查看地址的方式是不同的. 查看数组变量的地址,不需要使用 & ...

  3. 浅谈C中的指针和数组(二)

    原文转载地址:http://see.xidian.edu.cn/cpp/html/475.html 在原文的基础上增加自己的想法作为修改 很多初学者弄不清指针和数组到底有什么样的关系.我现在就告诉你: ...

  4. 浅谈C中的指针和数组(三)

    上一个博客我们得到了一个结论: 指针和数组根本就是两个完全不一样的东西.只是它们都可以“以指针形式”或“以下标形式”进行访问.一个是完全的匿名访问,一个是典型的具名+匿名访问.一定要注意的是这个“以X ...

  5. 浅谈c语言的指针

    对于非计算机专业的同学,c语言的指针往往就是老师的一句“指针不考“就带过了.c语言的指针号称是c语言的灵魂,是c语言中最精妙的部分. 指针本质上也是变量,也就是一段内存,只是他的特殊之处是他存储的数据 ...

  6. 浅谈C中的指针和数组(四)

    原文转载地址:http://see.xidian.edu.cn/cpp/html/476.html 在原文的基础上增加自己的思想作为自己的修改 指针数组和数组指针的内存布局 初学者总是分不出指针数组与 ...

  7. 浅谈C中的指针和数组(六)

    数组和指针,原本不想在写了,觉得这部分差不多了,但是自己在写程序的时候还是发现了一个错误.首先说一下我的要求: 给一个函数传递一个二维数组,然后我想在这个函数里面计算这个数组的行数. 写个类似的错误D ...

  8. 浅谈C中的指针和数组(七)

    现在到揭露数组名本质的时候了,先给出三个结论: (1)数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组: (2)数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量: ( ...

  9. 浅谈C语言中的强符号、弱符号、强引用和弱引用

    摘自http://www.jb51.net/article/56924.htm 浅谈C语言中的强符号.弱符号.强引用和弱引用 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014- ...

随机推荐

  1. c++中双冒号的作用

    双冒号(::)用法 参考链接:https://segmentfault.com/a/1190000000345680 1.表示“域操作符”例:声明了一个类A,类A里声明了一个成员函数void f(), ...

  2. Linux学习之CentOS(五)--CentOS下VMware-Tools安装

    已经进入到了Linux学习之CentOS的第六篇随笔了,所以这里就介绍一下VMware-Tools的安装. VMware-Tools的安装 VMware-Tools 主要的功能就是让用户在虚拟机和真实 ...

  3. ubuntu部署mipsel64交叉编译环境

    最近找到个不错的交叉工具链,据传能够编译mipsel64的程序,决定试试. 首先当然是安装环境: apt install -y gcc libncursesada3-dev 下载,解压,进入 三部曲: ...

  4. ABP文档笔记 - 配置、设置、版本、功能、权限

    配置 全局仅一个单例,保存一组配置信息,一般直接在模块的预启动事件中赋值or修改.没有Scope划分,无论租户还是房东亦或者用户读取的值都不会有差异.每个模块都可以扩展这个配置. 设置 它没有层级关系 ...

  5. 用tensorlayer导入Slim模型迁移学习

    上一篇博客[用tensorflow迁移学习猫狗分类]笔者讲到用tensorlayer的[VGG16模型]迁移学习图像分类,那麽问题来了,tensorlayer没提供的模型怎么办呢?别担心,tensor ...

  6. 再见,segmentfault

    再见,segmentfault 太多的Bug,对segmentfault已经爱不起了. 重回博客园~

  7. git 覆盖本地变化

    git fetch && git reset --hard origin/master

  8. Dynamics CRM 部署NLB后使用群集名称访问弹验证框验证不过的解决方法

    自上次部署NLB到现在已有段时间了,今天部署完后遇到了个问题,上次也遇到过但忘记了,本篇作为对该问题的一个记录,部署文档:https://blogs.msdn.microsoft.com/niran_ ...

  9. Android 结合实际项目学会ListView局部刷新和相关知识《一》

    转载本专栏博客,请注明出处:道龙的博客 最近在公司参与的项目中有一个界面需要做局部UI更新处理,把其化烦为简为Demoi形式写在这里.我们还是运行该Demo,知道ListView局部刷新的使用场景:( ...

  10. 解决 oracle IO占用率很高的问题

    突然user io占用率很很高,看了一个AWR报告,发现direct path read temp,direct path write temp的的数率很高,后来怀疑是临时表空间不够了,就试着设了一下 ...