在C语言中,int *p = &a
int *p;
声明了一个指向整数类型的指针p
。&a
是取变量a
的地址,&
是取地址运算符。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;
如果是这样写的代码,那么编译器将报错,因为类型不能兼容(这会让编译器很困扰)
Comments NOTHING