#include <stdio.h>
void go_south_east(int lat, 【传入latitude和longitude】int lon)
{
lat = lat -1;【维度减小】
lon = lon【维度增加】 +1;
}
int man( )
{
int latitude = 32;
int longitude = -64;
go_south_east( latitude, longitude);
pr'intf ("停!当前位置: [%i,%i]\n", latitude, longitude );
return 0;
}
C语言按值传递参数
一开始,main()函数有 一个叫longitude的局部变量,它的值是32
当计算机调用go_ south_ east()函 数时,它将变量longitude的值复制给了参数lon,这只是一个赋值的过程,从变量longitude到变量lon。也就是说,当调用函数时,作为参数传递的不是变量,而只是变量的值。
当go_ south_ east()函数修改了lon的值时,函数只是修改了本地的副本,也就是说程序返回main()函数时,变量longitude中保存的还是它原来的值32。
指针让存储器易于共享
使用指针的主要原因之一就是让函数共享存储器。一个函数可以修改另个函数创建的数据,只要它知道数据在存储器中的位置。
为了使用指针读写数据,需要有三个条件
1.得到变量的地址。
可以用&运算符找到变量保存在存储器中的位置
int x = 4;
printf("x lives at %p\n",【%p格式符将地址以16进制(以16为基数)的格式输出。】 &x【&运算符将找到变量的地址:4100 000】) ;
一旦得到了变量的地址,就需要把它保存在某个地方。为此,需要指针变量。指针变量是一个用来保存存储器地址的变量。当声明指针变量时,需要说明指针所指向的地址中保存的数据的类型:
【这是一个指针变量,它保存的是一个地址,这个地址中保存的是一个int型变量】int *address_of_x = &x;
2.读取地址中的内容
当有了存储器地址,就想读取保存在那里的数据,这时可以用*运算符:
int value_stored = *address_of_x;【它会读取address_of_x所给出的存储器地址中的内容。它将会被设置为4:这个值是一开始就保存在变量x中的值】
*运算符和&运算符恰好相反。&运算符接收一个数据,然后告诉程序员这个数据保存在哪里,$运算符接收一个地址,然后告诉程序员这个地址中保存的是什么数据。因为指针有时也叫引用,所以*运算符也可以描述成对指针进行解引用。
3.改变地址中的内容。
如果有一个指针变量,并想修改这个变量所指向地址中的数据,可以再次使用*运算符,只不过这次需要把指针变量放在赋值运算符的左边。
*address_of_x = 99;【他会把原x变量的内容改成99】
1 #include<stdio.h>
2 void go_ south east( int *lat, int *lon)【参数将保存指针变量,因此它们必须是int *类型】
{
*lat = *lat -1;【*lat可以读取旧的值,并设置新的值】
*lon = *lon +1;
}
int main( )
{
int latitude = 32;
int longitude = -64;
go_south_east( &lat tude , &longitude );【需要用&运算符来找到latitude和longitude变量在存储期中的地址】
printf ("停!当前位置:[%i, %i]\n" , latitude , longintude);
return 0;
}
要点
计算机会为变量在存储器中分配空间。
局部变量位于栈中。
全局变量位于全局量段。
指针只是一个保存存储器地址的变量。
&运算符可以找到变量的地址。
*运算符可以读取存储器地址中的内容。
*运算符还可以设置存储器地址中的内容。
指针是进程存储器中真实编号的地址。
计算机会为每个进程分配一个简版存储器,看起来就像是一长串字节。
实际的存储器复杂多了,但细节对进程隐藏了起来,这样操作系统就可以在存储器中移动进程,或释放并重新加载到其他位置。
物理存储器的结构十分复杂,计算机通常会将存储器地址分组映射到存储芯片的不同的存储体(memory bank)。
我们打印指针时不一定要用上%p,在大多数的现代计算机上可以用%li,但编译器会给出警告
%p以十六进制表示存储器的值是因为工程师通常以十六进制表示存储器地址。