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

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

  [复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
本帖最后由 行者~ABC 于 2020-11-10 10:11 编辑
& M4 ~5 e9 \+ ]+ P, Z2 C' V
' I" N- Q. M* B' _" S& g
指针,想说弄懂你不容易啊!我们许多初学指针的人都要这样感慨。我常常在思索它,为什么呢?其实生活中处处都有指针,我们也处处在使用它。有了它我们的生活才更加方便了。没有指针,那生活才不方便。不信?你看下面的例子。
1 q' j, n- @  D) x0 U
这是一个生活中的例子:比如说你要我借给你一本书,我到了你宿舍,但是你人不在宿舍,于是我把书放在你的2层3号的书架上,并写了一张纸条放在你的桌上。纸条上写着:你要的书在第2层3号的书架上。当你回来时,看到这张纸条,你就知道了我借与你的书放在哪了。你想想看,这张纸条的作用,纸条本身不是书,它上面也没有放着书。那么你又如何知道书的位置呢?因为纸条上写着书的位置嘛!其实这张纸条就是一个指针了。它上面的内容不是书本身,而是书的地址,你通过纸条这个指针找到了我借给你的这本书。
% B, T# Y/ k, F) O
计算机中所有的数据都必须放在内存中,不同类型的数据占用的字节数不一样,例如 int 占用4个字节,char 占用1个字节。为了正确地访问这些数据,必须为每个字节都编上号码,就像门牌号、身份证号一样,每个字节的编号是唯一的,根据编号可以准确地找到某个字节。

; D0 ^$ f6 C) l6 z- ?
下图是 4G 内存中每个字节的编号(以十六进制表示):

9 W$ P" g+ \' _
我们将内存中字节的编号称为地址(Address)或指针(Pointer)。地址从 0 开始依次增加,对于 32 位环境,程序能够使用的内存为 4GB,最小的地址为 0,最大的地址为 0XFFFFFFFF。

9 `  I6 I, E5 c: @7 o5 o; G5 T7 X
下面的代码演示了如何输出一个地址:
#include <stdio.h>
int main(){
    int a = 100;
    char str[20] = "c.biancheng.net";
    printf("%#X, %#X\n", &a, str);
    return 0;
}
运行结果:
0X28FF3C, 0X28FF10
1 O1 T* h: O) f" r/ @
%#X表示以十六进制形式输出,并附带前缀0X。a 是一个变量,用来存放整数,需要在前面加&来获得它的地址;str 本身就表示字符串的首地址,不需要加&。
一切都是地址

  N: W: T$ B! D. L1 K. b
C语言用变量来存储数据,用函数来定义一段可以重复使用的代码,它们最终都要放到内存中才能供 CPU 使用。

" h" y. e% q* \
数据和代码都以二进制的形式存储在内存中,计算机无法从格式上区分某块内存到底存储的是数据还是代码。当程序被加载到内存后,操作系统会给不同的内存块指定不同的权限,拥有读取和执行权限的内存块就是代码,而拥有读取和写入权限(也可能只有读取权限)的内存块就是数据。
4 B$ Z  E# t2 M
CPU 只能通过地址来取得内存中的代码和数据,程序在执行过程中会告知 CPU 要执行的代码以及要读写的数据的地址。如果程序不小心出错,或者开发者有意为之,在 CPU 要写入数据时给它一个代码区域的地址,就会发生内存访问错误。这种内存访问错误会被硬件和操作系统拦截,强制程序崩溃,程序员没有挽救的机会。

! R  H/ a5 d1 ~9 b. q) B( @
CPU 访问内存时需要的是地址,而不是变量名和函数名!变量名和函数名只是地址的一种助记符,当源文件被编译和链接成可执行程序后,它们都会被替换成地址。编译和链接过程的一项重要任务就是找到这些名称所对应的地址。
, ]; _* I% o( I# u3 ]" V. B% c. H
假设变量 a、b、c 在内存中的地址分别是 0X1000、0X2000、0X3000,那么加法运算c = a + b;将会被转换成类似下面的形式:
0X3000 = (0X1000) + (0X2000);
( )表示取值操作,整个表达式的意思是,取出地址 0X1000 和 0X2000 上的值,将它们相加,把相加的结果赋值给地址为 0X3000 的内存

2 [/ F0 v% a2 p' J$ @
变量名和函数名为我们提供了方便,让我们在编写代码的过程中可以使用易于阅读和理解的英文字符串,不用直接面对二进制地址,那场景简直让人崩溃。

- l; _* L$ \' E' j9 s0 m
需要注意的是,虽然变量名、函数名、字符串名和数组名在本质上是一样的,它们都是地址的助记符,但在编写代码的过程中,我们认为变量名表示的是数据本身,而函数名、字符串名和数组名表示的是代码块或数据块的首地址。$ z7 {) i! \, `! y) g* S& {

* N, }  ?7 J) T3 d* i2 T
# X8 Z3 O% R  P9 I
[/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 | 只看该作者
    看看                        0 N. {3 }/ d, k) C0 ]& s/ v
  • TA的每日心情
    开心
    2020-4-8 15:26
  • 签到天数: 1 天

    [LV.1]初来乍到

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

    该用户从未签到

    6#
    发表于 2019-10-8 09:43 | 只看该作者
    5 A+ Q* s2 b% A& ~- I
    非常好~学习一下~
  • TA的每日心情
    奋斗
    2023-2-7 15:02
  • 签到天数: 206 天

    [LV.7]常住居民III

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

    该用户从未签到

    8#
    发表于 2019-10-8 16:17 | 只看该作者
    谢谢楼主分享& F1 T0 u7 [0 ~& [8 x% J
  • TA的每日心情
    开心
    2023-2-12 15:39
  • 签到天数: 1 天

    [LV.1]初来乍到

    12#
    发表于 2019-10-12 16:22 | 只看该作者
    通俗易懂...10086个赞!6 i+ J4 f% \  K% u

    该用户从未签到

    13#
    发表于 2019-10-12 16:31 | 只看该作者
    66666666666664 k3 M7 `: v5 G" }
  • TA的每日心情
    奋斗
    2021-12-29 15:54
  • 签到天数: 13 天

    [LV.3]偶尔看看II

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

    该用户从未签到

    15#
    发表于 2019-10-21 16:15 | 只看该作者
    不错 不错 不错  不错 不错  不错 不错 不错 不错 不错; t/ Y1 `0 o- W+ \% D2 y+ o& `
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-7-21 05:56 , Processed in 0.156250 second(s), 28 queries , Gzip On.

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

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

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