在x.c中定义了一个字符数组 char s[100],
在l.c中进行引用extern char s[200], 有些c程序新手经常把它写成extern char *s。 这两种写法的含义一样吗?

首先得理解声明与定义的含义:
定义一个变量意味着要给它进行内存分配, 而声明一个变量则可以在其他文件中, 只是进行一种声明, 表示有这个变量存在, 但是在其他文件中定义, 声明后不用分配内存。

我们看一下extern char s[100]与extern char *s在执行s[10]的取值过程是什么样的:

1、 extern char s[100], s是个符号, 它既是一个数组的名称, 又是数组的起始地址(作为名称是因为他是一个标号,作为地址是因为symbol代表的就是一个地址), 假设编译器在编译的时候给s分配的地址是6789, 那么程序在执行s[10]的时候, 先找到s符号的地址6789, 然后在取(6789+10)地址上的内容。

2、extern char *s它声明了s是个指针, 既然是指针, 那么取址的过程就是间接的。 s这个符号在编译的时候也是有地址的, 不过这个地址上的内容又是一个地址, 在这个地址上保存的才是要存取的内容。当在x.c中定义s为字符数组后, 在l.c中声明s却是个指针, 这样在用s[10]操纵的时候会出现什么问题呢? 
s在x.c中被编译器分配的地址是6789, 在l.c中被当成指针了, 所以先找到6789这个地址, 在这个地址上取值作为内容的地址,6789上实际保存的是s[0]的值, 我们假设为'a', 然后程序会把'a'这个值当成地址, 然后去'a'这个地址上取内存内容, 'a'地址上显然存放的是内核数据段或代码段, 应用程序显然会报错的。 如果s[0]存放的即使是应用层程序可以访问的内容, 那么程序也会出现莫名其妙的bug。

所以c程序员一定要搞清数组和指针并不是完全相同的。

上面这段其实是在网上摘的,还有一点要说讲清楚:对于需要重定向的”标号“,在链接前,标号代表的地址都是零,以上面的文字中l.c为例,由于他不知道也不需要知道要链接的另一个文件是char []型的,所以对s的操作是按照指针来操作,将数组当作指针来操作当然会出错。

理解extern char s[100]与extern char *s的更多相关文章

  1. 字符串的高级应用-char a[100] = "1+2=;3-2=;2*5=;8/4=;" 得到char a[100] ="1+2=3;3-2=1;2*5=10;8/4=2;"

    1 #include<stdio.h> 2 #include<string.h> 3 4 int main() 5 { 6 char a[100] = "1+2=;3 ...

  2. 【转载】理解C语言中的关键字extern

    原文:理解C语言中的关键字extern 最近写了一段C程序,编译时出现变量重复定义的错误,自己查看没发现错误.使用Google发现,自己对extern理解不透彻,我搜到了这篇文章,写得不错.我拙劣的翻 ...

  3. char * p = "abc"与const char *p = "abc"

    char * p = "abc"与const char *p = "abc"的区别是什么呢? 第一个语句会产生问题: warning: deprecated c ...

  4. 20130324 LBP CSLBP 全局存储区 局部存储区 char c[]=”hello world”和char *str=”hello world”的区别

    1.LBP and CSLBP 2.再论char c[]=”hello world”和char *str=”hello world”的区别 /**************代码1************ ...

  5. char s[]字串和char *s字串有什麼区别?

    C語言有兩種字串宣告方式char s[]和char *s,兩者有什麼差異呢? Introduction char s[] = "Hello World"; (只是用字符串常量初始化 ...

  6. C语言char*字符串数组和unsigned char[]数组的相互转换

    #include <iostream> #include <string> using namespace std; void convertUnCharToStr(char* ...

  7. char a[] = "hello world1"和char *p = "hello world2";的区别(转)

    转自:jianchi88 http://blog.csdn.net/jianchi88/article/details/6876405 #include<stdio.h> int main ...

  8. Delphi7中的Char和XE中的Char

    我用FillChar()函数时,发现两个版本中的Char不一样. 在delphi7中 procedure TForm2.Button1Click(Sender: TObject); var s: ar ...

  9. char * const p和const char *p的区别

    1. 前者定义P为常量,即只能单向赋值一次,P++展开为p=p+1,重复赋值给常量,出错,后者P为地址变量,地址变量是指向该变量的存储地址值如:4B3F6A,不能赋给一个字符值(字符相当于ascii表 ...

随机推荐

  1. Linux 下cronolog分割catalina.out文件

    开发项目的时候查看日志,发现catalina.out已经有1个多G,日积月累的慢慢变大,幸亏及时发现还没有导致错误, tomcat默认日志之一输出在catalina.out文件中的,不会分割,不便于使 ...

  2. encodeURIComponent=>Uri.EscapeDataString

    javascript: encodeURIComponent=> C#: Uri.EscapeDataString http://stackoverflow.com/questions/5754 ...

  3. PHP 反射 ReflectionClass

    今天遇到了这样一个问题,如下代码: classA.php <?php class ClassA{ public function funcAa(){ } public function func ...

  4. 《APUE》第6章练习1

    问题:编写一个程序,它调用uname并输出utsname结构中的所有字段,并将输出与uname(1)命令的输出结构做比较. 我本来以为utsname结构也跟passwd结构一样,也有那三个函数来获取整 ...

  5. Ubuntu Android Studio/IntelliJ IDEA 支持文件中文命名

    Android Studio 默认字体无法使用中文命名文件,中文显示空心方块,使用思源字体,可解析 下载思源字体http://www.cnblogs.com/icgq/p/4195347.html 选 ...

  6. httpc服务器错误类型大全

    HTTP 400 - 请求无效HTTP 401.1 - 未授权:登录失败HTTP 401.2 - 未授权:服务器配置问题导致登录失败HTTP 401.3 - ACL 禁止访问资源HTTP 401.4 ...

  7. C盘清理大作战

    C盘会随着使用时间慢慢变满(即使你不在C盘装程序),下面就记录几个C盘清理的方法: 1.使用清理软件清理C盘(360卫视,腾讯管家) 2.转移虚拟内存:计算机右键属性——高级管理设置——高级——性能- ...

  8. Demo学习: ColumnSort

    ColumnSort 设置UniDGGrid点击表头时排序,设置方法比较麻烦且不通用,在实际开发中用处不大. 自己在项目中用了一个比较笨的办法,写了一个函数通过sql来排序: procedure TM ...

  9. CentOS7安装性能监控系统

    目录 系统描述. 开发环境. 开始之前. 安装influxdb数据库. 安装collectd 安装Grafana FAQ       influxdb的web界面没反应.   系统描述 想打造 New ...

  10. Linux tar 解压缩命令

    tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个 ...