在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. 提升程序的特权(AdjustTokenPrivileges)

    首先列出需要的函数 1.OpenProcessToken 2.AdjustTokenPrivileges 3. LookupPrivilegeValue ----------------------- ...

  2. 动态linq表达式新方法,Dynamic LINQ Extension Method

    Remember those old posts on Dynamic LINQ? You are probably aware that Microsoft has made its impleme ...

  3. mysql安装启动教程(两种方法)

    mysql安装启动: 方法一(简单版): cmd进入mysql安装的bin目录:mysqld.exe –install net start mysql  服务启动(或者选择计算机->(右键)管理 ...

  4. linux ubuntu 思源黑体安装

    下载地址: 全部:700多M  https://github.com/adobe-fonts/source-han-sans/releases/tag/1.001R 可选部分Github : http ...

  5. Dao层和Service层设计

    1.Dao接口层 public interface IBaseDao<T, ID extends Serializable>{ public abstract Serializable s ...

  6. 带搜索的下拉框Chosen

    一:参考 https://harvesthq.github.io/chosen/ Chosen是一个jQuery插件 二:引入js文件 <link href="plug-in/chos ...

  7. linux命令 chattr超级权限控件

    linux命令:chattr 1.作用 修改ext2和ext3文件系统属性(attribute),使用权限超级用户.   linux命令:chattr 1.作用修改ext2和ext3文件系统属性(at ...

  8. Mysql数据库备份和还原常用的命令

    Mysql数据库备份和还原常用的命令是进行Mysql数据库备份和还原的关键,没有命令,什么都无从做起,更谈不上什么备份还原,只有给系统这个命令,让它去执行,才能完成Mysql数据库备份和还原的操作,下 ...

  9. 【网络】 NAT

    NAT(Network Address Translation,网络地址转换)是1994年提出的.当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因 ...

  10. custom activities

    Useful Sharepoint Designer Custom Workflow Activities http://spdactivities.codeplex.com/ http://stac ...