指针的定义
指针变量也是一个变量。指针变量只能存放地址,不能将一个int变量直接赋值给指针
指针存放的内容是一个地址,该地址指向一块内存空间
计算机的内存最小单位是BYTE(字节),每一个BYTE的内存都有一个唯一的编号,这个编号就是内存地址,编号在32位系统下是一个32位的整数,在64位系统下是一个64位的整数
#include <stdio.h>
int main()
{
int a = 0 ;
int b = 0 ;
char buf[10];
printf("%p,%p,%p\n",&a,&b,buf);
int *p;//定义一个指针变量p
p = &a;//地址虽然是一个整数,但地址是一个特殊的整数,是不能直接通过整数来操作的
printf("%x\n",p);
int *p1;//定义一个变量p1,它指向一个int的地址
p1 = &b;//指针变量只能存放地址,不能将一个int变量直接赋值给指针
return 0;
}
&取地址运算符
&可以取得一个变量在内存中的地址
无类型指针
定义一个指针变量,但不指定它指向具体哪种数据类型;可以通过强制转化将void 转化为其他类型指针,也可以用void 将其他类型指针强制转化为void类型指针
#include <stdio.h>
int main()
{
int *p;
int a = 3;
p = &a;
int b = *p;//*p的意思是指针变量指向内存的内容
// printf("%d\n",b);
*p = 10;//通过指针间接修改指针指向的变量的值
// printf("a=%d\n",a);
char buf[10];
printf("%u,%u,%u,%u\n",buf,&buf[0],&buf[1],&buf[2]);
printf("-----------\n");
int buf1[10];
printf("%u,%u,%u,%u\n",buf1,&buf1[0],&buf1[1],&buf1[2]);
void *p3;//这个叫无类型指针,意思是这只是一个指针变量,而不指向任何具体的数据类>型
p3= NULL;//将指针赋值NULL,值为NULL的指针,叫做空指针
printf("%d\n",sizeof(p3));//32位系统指针占4个字节,64位系统占8个字节
return 0;
}
空指针
指向NULL的指针叫空指针,没有具体指向的指针叫野指针
#include <stdio.h>
int main()
{
int a = 10;
int *p;//p就是一个野指针,如果p运气好,指向一个程序有效地址,那么代码不会出错;如
//果指向的不是有效地址,则会导致程序崩溃
//程序中要避免野指针的存在,因为野指针是导致程序崩溃的主要原因
// p = &a;
*p = 1;
printf("a = %d\n",*p);
指针的兼容性
指针之间赋值比普通数据类型赋值检查更为严格,例如,不可以把一个double * 赋值给int *
原则上一定是相同类型的指针指向相同类型的变量地址,不能用一种类型的指针指向不同类型的变量地址
指向常量的指针与指针常量
const char *p;//定义一个指向常量的指针
char *const p;//定义一个指针常量,一旦初始化后,其内容不可改变
定义一个指向常量的指针
#include <stdio.h>
int main()
{
int a = 10;
int b = 30;
const int *p = &a;//p这个指针只能指向一个常量
// *p = 20;//不能通过这种方式,修改一个const指针
a = 20;
p = &b;
printf("a = %d\n",*p);//*p是个只读的值,不能修改
return 0;
}
定义一个指针常量
#include <stdio.h>
int main()
{
int a = 10;
int b = 30;
int *const p = &a;//定义一个常量指针,可以通过常量指针修改或读取一个变量的值.但是不可改变其指向的地址
*p = 20;
//error: assignment of read-only variable ‘p’
// p = &b;//错误,常量指针一旦定义了,那么就不能修改其指向的变量
printf("a = %d\n",*p);//
return 0;
}
指针与数组的关系
一个变量有地址,一个数组包含若干个元素,每个元素在内存中都有地址
int a[10]
int *p = a;
int main()
{
char buf[10] = {0,1,2,3,4};
char *p = &buf;
char *p1 = &buf[0];
char *p2 = &buf[1];
char *p3 = &buf[2];
*p2 = 7;
p3 +=1;//指针移动一位
*p3= 70;
printf("%d,%d,%d,%d\n",*p,*p1,*p2,*p3);
int i;
for(i=0;i<10;i++)
{
*p = i;
p++;
}
// print(buf);return 0;
//p已经指向数组的最后一个成员了
//p=buf;//将p的值重新指向了数组的首地址
p -= 10;
for(i=0;i<10;i++)
{
*p = i*10;
p++;
}
print(buf);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
//int ip转为字符串
void ipToString(int n)
{
unsigned char *p = &n;
printf("%u.%u.%u.%u\n",*p,*(p+1),*(p+2),*(p+3));
}
//字符串转为int ip
int stringToip(char s[])
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
sscanf(s,"%d.%d.%d.%d",&a,&b,&c,&d);
printf("a = %d,b=%d,c=%d,d=%d\n",a,b,c,d);
int ip = 0;
char *p = &ip;
*p = a;
p++;
*p = b;
p++;
*p = c;
p++;
*p = d;
p++;
return ip;
}
int main()
{
//IP地址的保存方法,通过int传递节省带宽(4个字节)
//192.168.1.1 = 11个字节
//232.222.333.444 = 15个字节
//IP在网络中传递的是一个DWORD,就 是一个int
int a = 0x12345678;
char *p = &a;
p++;
printf("%x\n",*p);//56
p++;
printf("%x\n",*p);//34
p++;
printf("%x\n",*p);//12
//192.168.8.253
int ip = 0;
unsigned char *p1 = &ip;
*p1 = 192;
p1++;
*p1 = 168;
p1++;
*p1 = 8;
p1++;
*p1 = 253;
printf("ip = %d\n",ip);
ipToString(ip);
char s[100] = "192.168.8.253";
int ss = stringToip(s);
printf("%d",ss);
return 0;
}