C语言指针 百思不得其解的一个问题
各位大神 最近在学指针遇到了个问题 为什么上面输出就不用 * 而下面就用*呢 我感觉指针是一直要用 *才能输出里面的内容的
char str[100] = "abcd";
char *p = &str;
printf("%s\r\n",p);
int num = 3;
int *a = #
printf("\r\n%d",*a);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
格式化字符串不一样,%s要求指针,%d要求整数
对于题主
我感觉指针是一直要用 *才能输出里面的内容的
这个说法,其实是不恰当的。指针和其它所有的变量一样,都是一种变量类型,都有
标识符
和值
两个属性。所有的值都是数字(因为计算机只能存01
,01
可以很直接转换为十进制数)。这个值如果直接读,是完全混乱的。比如,10
是什么?我即可以说是数字10
,也可以是ascii码为10
的那个字符
,还可以是指针
(其指向地址为10的那个变量)。所以,值
与标识符
与变量类型
绑定,三者共同解释一个变量。说这么多,就一句:变量都是统一的
。对于指针,也是一个这样通用的变量。题中的
p
与*p
与,*a
与a
其实没有本质区别。printf("%s\r\n",p)
。%s
表示输出从第二个参数(即p)
指向(p甚至不是指针都可以,C语言只是愚蠢地去得到p的值,然后找到地址为这个值的字符,这个就表示p指向的字符)的那个字符开始,一直到\0
结束 的字符串。如果你写成
printf("%s\r\n",*p)
,就表示*p
指向的地址(注意,不是p
指向的地址)而*p
的值是一个字符类型,对它的值代表的地址访问是非法不合理的,但c是自由的,应该会允许这样做。printf("\r\n%d",*a)
%d
是以十进制输出第二个参数(变量)的值,*a
代表以a
的值为地址的那个变量。所以,就是输出
a指向的那个变量的值,而如果是
printf("\r\n%d",a),它输出的就是
a的值,也就是是
num`变量的地址。说的比较乱,但都是自己的一些总结。题主不妨多理解下。
基本的数据类型 用的是指,数组 等非基本数据类型就是用指针!
特别是在格式化字符输出的时候,由于指定了格式化需要参数类型,在参数类型不匹配是不会强制转换.
或者是格式化字符需要的参数是指,但是传的是指针,那么它会把传递过去的指针地址当做指来处理!
所以在使用格式化字符输出时需要注意站位符与,参数之间的匹配!
ps:其实我觉得如果是刚学的话,可以重复造下轮子,把printf函数自己亲手实现一次就知道其中的原理了.
第一个输出中p为指向字符数组的指针,也代表了一个字符串,与printf里的%s匹配故不用。
第二个输出中a为指向整型变量的指针,所以a才与printf里的%d匹配。
用*表示要对该地址进行解引用,解引用就是取到该地址上的值。
但是%s就是需要首地址才能打印整个字符串。如果你对首地址解引用,那就只能取到首地址上的值(第一个字符),这时候你就要用%c了。
数组在堆中分配内存,str本身就是指向数组的第一个元素,赋值后p和str等价, 而普通类型在栈中,赋值后p和a不等价,p指向a,a指向值
p 实际上是字符指针,如果你要输出 p 指向的内容,就应该加 *,例如:
但是你在格式参数里使用了%s,表示输出字符串,所以就会尝试一直读取p指向的内容,直到遇到 '\0'。在C语言里使用 char* 表示字符串是一个特例,这个时候你可以把它看做一个整体,就好像:
%s意味着相应的参数为字符串数组的首地址,也就是str
运行以后可以发现,p和str的指是相同的
下面是我之前学习做的笔记,你凑合看一下
int (*func_p)();//指向int类型函数的指针
int *f();//返回指向int类型指针的函数
int num = 1;
int *p_num;
p_num = # //
*p_num//是取出num的数据
p_num//是取出num的内存地址
&P_num//是取出p_num的内存地址
p_num+1//是对num的内存地址加1 ,因为num是int类型的,占用4个字节,如果原来是0x000004那么加1后就是0x000008(数据只是测试随便写的),而不是对num的值计算
int arr[] = {1,2,3,4};
printf("%d\n",(arr+1));// 数组可以是分配好的连续指针,arr就是这个数组的首地址,对地址+1就是对这个类型+1,如果arr[0]是0x00004那么arr[1]就是0x00008然后前面的就是取地址值。 如果是int arr[][4]也可以写成int *arr[4];
printf("%d\n",*arr+1);//同上
(K&R 423页)
int arr[8][8];//int的数组
int **p;//指向int类型指针的指针
int *p[10];//具有10个元素的数组, 每个元素是一个指向int的指针
int (* p)[10];//一个指针, 指向有10个元素的int类型的数组
int * p[3][4];
int (* p) [3][4];
int (* p[3]) [4]; //具有3个元素的数组, 每个都是指向具有4个元素的int数组的指针
char *pd () //返回指向char的指针的函数
char (* pd)()//指向返回类型为char的函数的指针
char (* pd[3])()//由3个指针组成的数组,每个指针指向返回类型为char的函数
int const | const int p =&1 //p不能在修改了, p还可以使用
int const p = 1; //p不能在修改了,p还可以
const 在谁前面,修饰谁
第一个是声明一个常量的指针变量。指向的对象不可以修改但是P的指向可以修改。
第二个是声明一个指针变量P是常量类型,指向不可以修改但是指向的对象可以修改。