1.内存和地址操作符&
目录
在我们的计算机当中,每一个变量都有自己相应的地址,一个字节在自己相应的内存块,所以地址的另一个名字叫“指针”
int main()
{
int a = 1;
int b = 2;
int c = 3;
printf("a=%p\n", &a);
printf("b=%p\n", &b);
printf("c=%p\n", &c);
return 0;
}
我们可以看到,在32位的环境下,a,b,c的地址都比上一个变量多四个字节
内存编号=地址=指针
2.什么是指针?
指针顾名思义就是指向某一个地方的东西,在计算机中就是指向某一块内存,我们要有某个内存的地址才能使用到指针,一个简单的例子。*p=&a。就像你送一样东西给别人,你要知道对方的地址才能送达,&a就是对方的地址,*p就是对方的家。
3.指针变量的初始化和解引用操作符*
int main()
{
int a = 123;
int* p = &a;
printf("*p=%d\n", *p);
return 0;
}
我们使用一个取地址操作符&将a的地址存储在指针变量p中
int* p中的int是说明指针变量指向的变量是整型,“*”说明p是一个指针变量,p是变量的名称
解引用操作符*
int main()
{
int a = 123;
int* p = &a;
*p = 10;
printf("a=%d\n", a);
return 0;
}
我们可以看到第五行代码,我们使用了解引用操作符,将p指向的地址的变量改成了10,因为p指向的是a的地址,将其解引用来修改值。
4.指针的大小
int main()
{
printf("%zd\n", sizeof(char*));
printf("%zd\n", sizeof(short*));
printf("%zd\n", sizeof(int*));
printf("%zd\n", sizeof(double*));
return 0;
}
我们可以发现指针变量在32位环境下是四个字节,在64位环境下是8个字节,而且不同类型的指针所占用的字节都是相等的。
5.指针的运算
指针+-整数
int main()
{
int n = 10;
char* pc = (char*)&n;
int* pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc + 1);
printf("%p\n", pi);
printf("%p\n", pi + 1);
return 0;
}
我们可以看到pc+1与pc多跳了一个字节,而pi+1与pi多跳了四个字节,所以指针类型决定指针向前走多少个字节。
指针-指针
int test(char* s)
{
char* p = s;
while (*p != '\0')
p++;
return p - s;
}
int main()
{
printf("%d\n", tsst("abc123"));
return 0;
}
指针的关系运算
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = &arr[0];
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
while (p < arr + sz) //指针的⼤⼩⽐较
{
printf("%d ", *p);
p++;
}
return 0;
}
6.野指针
野指针就是没有明确表明指向某一块地方,内容是无知的,随机的。
造成野指针的原因如下:
指针为初始化
int main()
{
int* p;//指针未初始化,默认为随机值
*p = 10;
return 0;
}
指针访问越界
int main()
{
int arr[10] = { 0 };
int* p = &arr[0];
int i = 0;
for (i = 0; i <= 11; i++)
{
//当指针指向的范围超出数组arr的范围时,p就是野指针
*(p++) = i;
}
return 0;
}
指针指向空间被释放
int* test()
{
int n = 100;
return &n;
}
int main()
{
int*p = test();//n是局部变量,离开test函数时已经空间已被释放了,所以p是野指针
printf("%d\n", *p);
return 0;
}
7.传值调用和传址调用
我们来写一个函数来交换它的两个值
void Swap(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a=%d b=%d\n", a, b);
Swap(a, b);
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
为什么我们没有达到交换的效果呢?
原因是在我们的实参传过去的时候,x和y确实有得到我们20和30这两个数,但是x,y和a,b的地址不同,在离开Swap这个函数的时候,x和y的地址就访问不了了,所以我们的a和b就没有改到相应的值,我们该传地址来交换。
void Swap2(int*px, int*py)
{
int tmp = 0;
tmp = *px;
*px = *py;
*py = tmp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前:a=%d b=%d\n", a, b);
Swap1(&a, &b);
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}