11.3 下午 指针(接上文)

发布于 20 天前  23 次阅读


在C语言中,int *p = &a

  1. int *p; 声明了一个指向整数类型的指针 p
  2. &a 是取变量 a 的地址& 是取地址运算符。
  3. p = &a; 将变量 a 的地址赋值给指针 p,这样 p 就指向了 a

在32位操作系统中,指针占4个字节(32位),这个尤其重要(你用printf函数+sizeof函数打印出来就知道了),而在64位操作系统里面,指针是占8个字节(和long好像)

比如说,变量a的地址是0x100,虽然变量 a 的地址(例如 0x100)在表示上是一个数值,但这个地址的存储(即指针的存储)在32位系统中占用4个字节,在64位系统中占用8个字节

int a;       // 声明一个整数变量 a
int *p = &a; // 声明一个指针 p,并将 a 的地址赋值给 p
*p = 100;    // 通过指针 p 修改 a 的值

*号有两种含义,第一个是在定义的时候(前面有变量类型的声明),表示后面的变量是指针,这里的 类型+*,比如int *可以理解成一个东西,它俩才是一个整体

第二个就是使用的使用,*号表示取值,即取这个指针指向的地址(也就是这个变量 a 所在的内存空间)的值

所以上面的*p = 100这行代码通过解引用指针 p即使用 *p),直接访问 p 指向的地址(a的内存空间),并将其值设置为 100


char ch = 'a';
char *q = &ch;

假如ch 在内存中的地址是 0x200,那么在0x200这个地址上存储的值是 ASCII 值 97(即字符 'a'

char *q = &ch; 这行代码声明了一个字符指针 q,并将其初始化为指向 ch 的地址。这将返回 ch 在内存中的地址(在这个例子中是 0x200)。因此,指针 q 的值将是 0x200(极为重要),而*q等价于变量a

通过指针 q,你可以访问和修改 ch 的值

那么再来看看int *和char *有什么不一样,已经知道,它们在数据类型、内存大小、解引用(一个返回整数值,一个返回字符值)时肯定是有区别的,但是,我们应尤为关注它们在指针算术上的区别

指针算术运算的结果和指针所指向的数据类型的内存大小密切相关

  • 对于 int *,如果你对指针进行加法操作(例如 q++),指针将增加 4(在 32 位系统上),因为 int 占用 4 个字节
  • 对于 char *,如果你对指针进行加法操作(例如 q++),指针将增加 1,因为 char 占用 1 个字节

//注意上面的q不加解引用符号(*),加4、加1的不同说明了一个指针增加的地址数步长)是与指针变量的数据类型对应的(不是说一定是4的指针),都是表示指向了下一个整数/字符

我们再次假设int变量a的地址是0x100(这个说话必须得纠正,昨天谈到,通常一个内存单元就是1个字节,int占4字节,所以准确地来说

  • a 的地址 0x100 存储 a 的最低字节(即 a 的第一个字节)
  • a 的地址 0x101 存储 a 的第二个字节
  • a 的地址 0x102 存储 a 的第三个字节
  • a 的地址 0x103 存储 a 的最高字节

即,a的内存空间(这里说的内存空间这个词和“地址”是等价的)是四个内存单元


为什么指针只取最低字节地址?

在大多数操作系统中,数据类型的地址通常是对齐的。例如,int 类型的地址通常是 4 字节对齐的

当你使用指针访问 int 类型的变量时,指针会使用最低字节地址(即 0x100来访问整个 int 变量。这里指针的类型(如 int *会告诉编译器如何解释从这个地址开始的内存内容

char ch='a';
int *q=&ch;

如果是这样写的代码,那么编译器将报错,因为类型不能兼容(这会让编译器很困扰)

届ける言葉を今は育ててる
最后更新于 2024-11-05