找回密码
 注册
关于网站域名变更的通知
查看: 14653|回复: 148
打印 上一主题 下一主题

C语言指针很难吗?请看这

  [复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-9-30 10:58 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
本帖最后由 行者~ABC 于 2020-11-10 10:11 编辑
7 e% c# Y+ V: J& X" E' F
; g% ]( U4 E5 v9 l( Q" o
指针,想说弄懂你不容易啊!我们许多初学指针的人都要这样感慨。我常常在思索它,为什么呢?其实生活中处处都有指针,我们也处处在使用它。有了它我们的生活才更加方便了。没有指针,那生活才不方便。不信?你看下面的例子。
0 Y- D6 s: @$ H( }: M1 G1 E
这是一个生活中的例子:比如说你要我借给你一本书,我到了你宿舍,但是你人不在宿舍,于是我把书放在你的2层3号的书架上,并写了一张纸条放在你的桌上。纸条上写着:你要的书在第2层3号的书架上。当你回来时,看到这张纸条,你就知道了我借与你的书放在哪了。你想想看,这张纸条的作用,纸条本身不是书,它上面也没有放着书。那么你又如何知道书的位置呢?因为纸条上写着书的位置嘛!其实这张纸条就是一个指针了。它上面的内容不是书本身,而是书的地址,你通过纸条这个指针找到了我借给你的这本书。
  G/ J- r& i( y  Y( e$ i( G
计算机中所有的数据都必须放在内存中,不同类型的数据占用的字节数不一样,例如 int 占用4个字节,char 占用1个字节。为了正确地访问这些数据,必须为每个字节都编上号码,就像门牌号、身份证号一样,每个字节的编号是唯一的,根据编号可以准确地找到某个字节。

9 J* A" {& g: j& p: v8 V
下图是 4G 内存中每个字节的编号(以十六进制表示):

+ u3 ~9 B7 n! F9 _. ?1 Q5 `
我们将内存中字节的编号称为地址(Address)或指针(Pointer)。地址从 0 开始依次增加,对于 32 位环境,程序能够使用的内存为 4GB,最小的地址为 0,最大的地址为 0XFFFFFFFF。

- J3 Q* r, s! ^; U9 C
下面的代码演示了如何输出一个地址:
#include <stdio.h>
int main(){
    int a = 100;
    char str[20] = "c.biancheng.net";
    printf("%#X, %#X\n", &a, str);
    return 0;
}
运行结果:
0X28FF3C, 0X28FF10
/ V, O+ J5 O2 _* M; F  m, L
%#X表示以十六进制形式输出,并附带前缀0X。a 是一个变量,用来存放整数,需要在前面加&来获得它的地址;str 本身就表示字符串的首地址,不需要加&。
一切都是地址
$ Y5 x% ~5 C% @' d
C语言用变量来存储数据,用函数来定义一段可以重复使用的代码,它们最终都要放到内存中才能供 CPU 使用。
6 \% |6 v6 F/ o' z/ x
数据和代码都以二进制的形式存储在内存中,计算机无法从格式上区分某块内存到底存储的是数据还是代码。当程序被加载到内存后,操作系统会给不同的内存块指定不同的权限,拥有读取和执行权限的内存块就是代码,而拥有读取和写入权限(也可能只有读取权限)的内存块就是数据。
. v: x2 b  n6 L3 V( X8 p
CPU 只能通过地址来取得内存中的代码和数据,程序在执行过程中会告知 CPU 要执行的代码以及要读写的数据的地址。如果程序不小心出错,或者开发者有意为之,在 CPU 要写入数据时给它一个代码区域的地址,就会发生内存访问错误。这种内存访问错误会被硬件和操作系统拦截,强制程序崩溃,程序员没有挽救的机会。
& ?/ `( J' A# O
CPU 访问内存时需要的是地址,而不是变量名和函数名!变量名和函数名只是地址的一种助记符,当源文件被编译和链接成可执行程序后,它们都会被替换成地址。编译和链接过程的一项重要任务就是找到这些名称所对应的地址。
2 U2 L: h/ S! L7 c2 s/ a$ Z
假设变量 a、b、c 在内存中的地址分别是 0X1000、0X2000、0X3000,那么加法运算c = a + b;将会被转换成类似下面的形式:
0X3000 = (0X1000) + (0X2000);
( )表示取值操作,整个表达式的意思是,取出地址 0X1000 和 0X2000 上的值,将它们相加,把相加的结果赋值给地址为 0X3000 的内存

( l( [3 y% n) |' _
变量名和函数名为我们提供了方便,让我们在编写代码的过程中可以使用易于阅读和理解的英文字符串,不用直接面对二进制地址,那场景简直让人崩溃。

1 p  T: _& t) B- G
需要注意的是,虽然变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符,但在编写代码的过程中,我们认为变量名表示的是数据本身,而函数名、字符串名和数组名表示的是代码块或数据块的首地址。3 W% V! }: b' Q7 [6 B7 y  D

+ C, Y: ^$ B  T6 f$ l

, v9 E6 t5 u5 j6 q9 o* l$ e" l[/hide]

该用户从未签到

推荐
发表于 2021-5-26 11:24 | 只看该作者
通过指针,可以简化一些 C 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C 程序员,学习指针是很有必要的。  正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址。

该用户从未签到

推荐
发表于 2020-6-17 15:57 | 只看该作者
看看                        3 V7 C2 R+ C0 T: B# G
  • TA的每日心情
    开心
    2020-1-14 15:37
  • 签到天数: 2 天

    [LV.1]初来乍到

    推荐
    发表于 2020-1-13 10:30 | 只看该作者
    看看                        - D6 x6 i; Z* t% [# K
  • TA的每日心情
    开心
    2020-4-8 15:26
  • 签到天数: 1 天

    [LV.1]初来乍到

    5#
    发表于 2019-9-30 16:46 | 只看该作者
    非常好~学习一下~

    该用户从未签到

    6#
    发表于 2019-10-8 09:43 | 只看该作者
    6 o! a7 H, ?- U% \, k. ?6 T. R* f# ?
    非常好~学习一下~
  • TA的每日心情
    奋斗
    2023-2-7 15:02
  • 签到天数: 206 天

    [LV.7]常住居民III

    7#
    发表于 2019-10-8 10:54 | 只看该作者
    看看,多谢分享

    该用户从未签到

    8#
    发表于 2019-10-8 16:17 | 只看该作者
    谢谢楼主分享$ \0 R& M5 [3 [" U) n7 ~
  • TA的每日心情
    开心
    2023-2-12 15:39
  • 签到天数: 1 天

    [LV.1]初来乍到

    12#
    发表于 2019-10-12 16:22 | 只看该作者
    通俗易懂...10086个赞!9 j3 h0 e4 P1 n6 ^

    该用户从未签到

    13#
    发表于 2019-10-12 16:31 | 只看该作者
    6666666666666
    6 ^% }& c7 W0 y8 ~+ T
  • TA的每日心情
    奋斗
    2021-12-29 15:54
  • 签到天数: 13 天

    [LV.3]偶尔看看II

    14#
    发表于 2019-10-14 13:46 | 只看该作者
    看看怎么样

    该用户从未签到

    15#
    发表于 2019-10-21 16:15 | 只看该作者
    不错 不错 不错  不错 不错  不错 不错 不错 不错 不错; |# k- {0 V; d5 y' z# t
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-6-21 17:32 , Processed in 0.093750 second(s), 28 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表