C语言之指针


一、指针的声明

指针的使用通常分两步:

1、int *p = &a;

2、*p = 10;

int main()
{
int a = 10;

int *p = &a;  //声明指针变量,并且把a的地址赋值给指针变量p

*p = 20;  //把20赋值给指针p所指向的内存,即a

printf("%d\n", a);
return 0;
}

上述代码内存示意图如下:


*p = 20;的时候,也就是把a的值改为了20,因为p指向的是a内存块。

 

注意:

1、两个*号含义不同,第一个*表示这是一个指针变量,是一个一个标识;第二个*表示指针p指向的内存

2、指针变量只能存储地址

3、指针只能指向和指针相同类型的变量

4、指针所指向的内存块的大小等于指针类型所占的字节数


二、指向指针的指针

int main()
{
int a = 10;
int *p = &a;  //可以理解为int * 就是指针p的类型
int **pp = &p;  //所以指向p的指针必须是int * 类型,声明新的指针为*pp,加上类型就是int **pp
**pp = 20;
printf(“%d\n”, a);  //输出为20
}

以上代码内存示意图如下:

三、指针与数组


int main()
{
int ages[5] = {10, 9, 8, 67, 56};
int *p = ages;  //定义一个指针变量指向数组第一个元素的地址,也是指向数组的地址
for(int i=0; i<5; i++)
{
printf(“%d\n”, *(p + i));  //p+i就是数组中i元素的地址,p+i不是正常的算术计算,而是指针p的地址加上指针类型字节数的地址,i的大小取决于指针的类型
printf(“%d\n”, p[i]);  //等同于上面的写法
}
return 0;
}
//---------------------------------------------------------------------------------------------------------
int main()
{
int ages[5];  //ages数组的大小为20个字节
change(ages);  //但是当数组作为参数的时候,传入的是数组的指针
return 0;
}

void change(int *array)  //等同于下面的方法,只不过下面的方法在编译的时候会警告,所以此方法才是接收数组参数的正确写法
{
int s = sizeof(array);
printf(“%d\n”, s);  //所以输出为8
}
/*
void change(int array[])  //此方法编译时候会被警告,所以应该使用上边的方法接收数组参数
{
int s = sizeof(array);
printf(“%d\n”, s);  //所以输出为8
}*/

数组形参接收的是实参数组的元素地址,理解如下图:

int main()
{
	// 20个字节
	int ages[5] = {10, 11, 19, 78, 67};
	change(&ages[2]);
	return 0;
}

// 利用一个指针来接收一个数组, 指针变量array指向了数组的首元素
void change(int *array)
{
	printf("%d\n", array[2]);	// array[2]等同于*(array+2)
}

四、数组与字符串


int main()
{
char *name2 = “it”;  //指针指向的是数组中首元素的地址,即“i”的地址
printf(“%c\n”, *name2);  //输出为 “i”,*name2的意思为指针name2指向地址所在的内存块

printf(“%s\n”, name2);  //name2为数组的地址,也是数组首元素的地址,%s意味着从name2所在地址的内存开始计算,遇到“\0”结束,所以输出为整个字符串,即“it”

return 0;
}

内存示意图如下:

C语言内存分为常量区、堆、栈

常量区存放常量字符串

堆存放对象

栈存放局部变量


使用指针声明字符串时,字符串为常量,不可更改,如下:

int main()
{
char *name2 = “it”;
*name2 = ‘T’;  //错误的写法,指针声明字符串不可更改
char *name3 = “it”;  //这里的”it”是常量
printf(“%p\n%p\n”, name2, name3);  //name2和name3指向同一地址
return 0;
}

字符串与数组总结:


五、指针数组和字符串输入

保存字符串数组的两种方式:

1char names[3][10] = {“jack”, “rose”, “tom”};

2char *names[5] = {“jack”, “rose”, “tom”};

int main()
{
char *names[5] = {“jack”, “rose”, “tom”};
printf(“%p\n”, names[0]);  //“j”的地址
printf(“%c\n”, *names[0]);  //“j”地址的内容
printf(“%s\n”, names[0]);  //输出为“jack”
printf(“%c\n”, names[0][1]);  //输出为“a”
}


六、返回指针的函数

#include <stdio.h>
char *test();

int main()
{
char *name = test();
printf(“name=%s\n”, name);
return 0;
}

char *test()
{
return “rose”;
}

七、指向函数的指针

void test()
{
printf(“......”);
}
int main()
{
void (*p)();  //定义指向函数的指针,void表示这个指向的函数没有返回值;()表示指向的函数没有参数
p = test;  //函数名就是函数的地址,把函数的地址给p
(*p)();  //通过指针间接调用函数
p();  //同上
test();  //直接调用函数
}





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值