这是一篇学习笔记,用来梳理一下这两天学到的知识,帮助加深理解。PS.刚刚接触数据结构,如果有哪里写的不妥当或者不对,还请大家指出!
基本类型指针在地址中的存放
指针类型变量定义后系统就会为其分配内存空间,对于定义的不同类型的指针变量,应该占几个字节?
对于32位的系统,每次可以操作32位(32个01)即可以一次操作从00...00-11..11的地址。而指针作为一种对地址的操作,要能够访问任意一个字节。所以32位系统中任何指针所占的字节都是32/8=4个。? 同理在64位系统中任何指针所占的字节都是64/8=8个。
#include <stdio.h>
int main (){
char a = 'A';
int b = 10;
double c = 19.7;
char *p = &a;
int *q = &b;
double *r = &c;
printf("%d %d %d", sizeof(p), sizeof(q), sizeof(r));
return 0;
}
输出:8 8 8
swap函数
第一种写法(不能完成交换):
void swap(int a, int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int x = 3, y = 5;
swap(x, y);
}
程序运行时会函数发生压栈,main函数、swap函数先后入栈,并为变量申请内存空间。swap函数中的形参a,b在栈区中申请的时临时空间,函数调用结束后就会释放。
main函数调用swap函数,形参a,b就会“拷贝”实参x,y的值。所以在swap函数中交换的实际上是“拷贝”过实参x,y的值之后的形参a,b。然而在函数调用结束之后swap函数申请的临时空间就被释放了,实参的值并没有被改变,交换失败。
第二种写法:(不能完成交换)
void swap(int *a, int *b)
{
int *temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int x = 3, y = 5;
swap(&x, &y);
printf("x=%d y=%d", x, y);
}
swap函数中定义指针形参,main函数中传入的是实参x,y的地址。此时在swap函数中交换的是指针变量a,b的内容,实参a,b的值并没有交换。
eg:定义实参x,y会为其分配静态内存,假设x,y的地址分别是0x12a1、0x12c1。在调用swap函数时,系统也会为swap函数中的形参a,b分配临时内存空间,假设a,b的地址分别是0x66a1、0x66c1。? main函数调用swap函数时,传给swap函数的是实参x,y的地址:0x12a1、0x12c1,故指针变量a,b的内容分别是0x12a1、0x12c1,交换之后指针变量a,b的内容分别是0x12c1,0x12a1
关于这一种写法,我认为在初学指针与理解swap函数的时候容易产生一点误区:swap函数交换了指针变量a,b的内容,也就是说指针变量a,b交换了各自所指向的逻辑地址,这时候很容易认为a,b所指向的地址发生交换,会导致实参x,y的地址随之交换。要说明的是,一旦一个变量(任意数据类型)被系统分配了内存空间,那么无论什么操作其地址都不会改变!上述交换的实质就是从p指向x、q指向y,变成了,q指向x、p指向y。
第三种写法:(可以完成交换) ?
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int x = 3, y = 5;
swap(&x, &y);
printf("x=%d y=%d", x, y);
}
实参x,y的逻辑地址传入指针变量a,b,此时栈区临时空间中的a,b就有了x,y逻辑地址的“拷贝”,之后通过指针运算符 * 直接访问物理地址(据说此过程存在关于线性地址的变换,不是太明白)实现对实参的直接操作,完成了对x,y值的交换。
|