指针是一种数据类型
1、指针也是一种变量,占有内存空间,保存内存地址
2、*p操作内存
- 在指针声明时,*号表示所声明的变量为指针
- 在指针使用时,*号表示操作指针所指向的内存空间中的值
- *p相当于通过地址(p变量的值)找到一块内存;然后操作内存
- *p放在等号的左边赋值(给内存赋值)
- *p放在等号的右边取值(从内存获取值)
3、指针变量和它指向的内存块是两个不同的概念
- 给p赋值p=&a,只会改变指针变量值,不会改变所指的内容(如p++,改变的只是指针的值,即指针指向下一个相邻的内存空间,并不是改变指向的内存空间的值)
- 给*p赋值*p=’a’,不会改变指针变量的值,只会改变所指的内存块的值
- 保证所指的内存块能修改,如初学者常犯如下错误:
char *getStr81()
{
char *tmp = NULL;
tmp = "abcdefgf";
return tmp;
}
void main()
{
char *p = getStr81();
printf("p:%s \n", p);
*(p+2) = 'r';
//经常出现的错误,字符串常量内存由操作系统管理,不能随意修改
system("pause");
return ;
}
- 指针是一种数据类型,是指它指向的内存空间的数据类型
含义:指针步长,根据所指向的内存空间的数据类型来确定 (如定义一个数组char a[100],a表示指向数组首元素的指针常量,因此a+1步长为1个字节。而&a表示的是指向整个数组a的指针,因此a+1步长为100字节)
【常见错误】直接向空指针中拷贝数据(没有事先分配内存)
char *p1 = NULL;
strcpy(p1, "abcdefg");
//报错,内存非法写入
当指针申明为NULL空指针时,编译器将其值设为0x0,这个内存地址收到操作系统控制和保护,因此不能进行修改,必须先分配内存后才能进行修改。
指针的间接赋值
1、指针间接赋值成立的三个条件
- 2个变量(通常一个实参,一个形参)
- 建立关系,实参取地址赋给形参指针
- *p形参去间接修改实参的值
2、一级指针的间接赋值
//条件1
int a = 10;
int *p = NULL;
//条件2
p = &a;
//条件3
*p = 30;
printf("a: %d \n", a);//输出为a:30
3、二级指针的间接赋值
char *p1 = NULL;
char **p2 = NULL;
p1 = 0x11;
p2 = 0x22;
p2 = &p1;
*p2 = 100;
【引申】n级指针可以给n-1级指针间接赋值
4、使用指针做函数参数实现模块封装
int getMem3(char **myp1, int *mylen1, char **myp2, int *mylen2)
{
int ret = 0;
char *tmp1, *tmp2;
tmp1 = (char *)malloc(100);
strcpy(tmp1, "1132233");
//间接赋值
*mylen1 = strlen(tmp1); //1级指针
*myp1 = tmp1; //2级指针的间接赋值
tmp2 = (char *)malloc(200);
strcpy(tmp2, "aaaaavbdddddddd");
*mylen2 = strlen(tmp2); //1级指针
*myp2 = tmp2; //2级指针的间接赋值
return ret;
}
int main()
{
int ret = 0;
char *p1 = NULL;
int len1 = 0;
char *p2 = NULL;
int len2 = 0;
ret = getMem3(&p1, &len1, &p2, &len2);
if (ret != 0)
{
printf("func getMem3() err:%d \n", ret);
return ret;
}
printf("p1:%s \n", p1);
printf("p2:%s \n", p2);
if (p1 != NULL)
{
free(p1);
p1 = NULL;
}
if (p2 != NULL)
{
free(p2);
p2 = NULL;
}
printf("p1:%d \n", p1);
system("pause");
return ret;
}