在下面给出的代码中,我声明了一个指向int的指针,我们都知道memcpy返回一个指向目标字符串的空指针,所以如果ptr是指向int的指针,那么为什么printf(“%s”,ptr);是完全有效的,ptr毕竟不是指向char的指针。
#include <stdio.h>
#include <string.h>
//Compiler version gcc 6.3.0
int main()
{
char a1[20] ={0} , a2[20] ={0};
int *ptr;
fgets(a1,20,stdin);
fgets(a2,20,stdin);
ptr = memcpy(a1,a2,strlen(a2)-1);
printf("%s \n",ptr);
if(ptr)
printf("%s",a1);
return 0;
}
为什么是printf(“%s”,ptr);这是完全正确的
事实并非如此——它可能会像预期的那样工作,但不能保证一定会成功。通过将错误类型的参数传递给printf
,您调用了未定义的行为,这意味着编译器不需要以任何特定方式处理这种情况。您可能会得到预期的输出,您可能会得到垃圾输出,您可能会得到运行时错误,您可能会破坏系统的状态,您可能会在宇宙的另一端打开一个黑洞。
首先考虑ptr=memcpy(a1, a2, strlen(a2)-1);
。传递给它的a2,因为指向任何不合格对象类型的指针可以转换为space*
或const space*
。(指向符合const
条件的对象类型的指针也可以转换为const space*
。)这遵循了C 20186.5.2.27中函数调用的规则(参数被转换为参数类型,就像通过赋值一样)和6.5.16 1(一个操作数是一个可能合格的无效*
,左边有所有的右的限定符)和6.5.16 2(右操作数转换为左的类型)。
然后memcpy
返回一个void*
,这是它的第一个参数(在转换为void*
后,我们尝试将其赋值给ptr
。这满足赋值的约束(其中一个操作数是void*
),因此它将指针转换为ptr
的类型,这是int*
。这由第6.3条规定。2.3 7:
指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针未正确对齐引用类型,则行为未定义。否则,当再次转换回来时,结果将等于原始指针...
由于a1
是一个未请求对齐的char
数组,因此它可以具有任何对齐方式。它可能不适用于int
。如果是这样的话,那么C标准不定义程序的行为。
如果a1
恰好对int
进行了适当的对齐,或者C实现成功地对其进行了转换,那么我们继续使用printf(“%s\n”,ptr)
。
printf
声明为int printf(const char*restrict,…)
。对于对应于
,没有要转换为的参数类型。而是执行默认参数升级。这些参数影响整数和
float
参数,但不影响指针参数。因此,ptr
作为int*
传递给printf
而不做任何更改。
对于
%s
转换,7.21中的printf
规则。6.1.8说“参数应是指向字符类型数组初始元素的指针。”当ptr
指向内存中与初始元素相同的位置时,它是指向int
的指针,而不是指向初始元素的指针。因此,这是一种错误的论点。
7.21.6.19说“…如果任何参数不是相应转换规范的正确类型,则行为未定义。”因此,C标准没有定义此程序的行为。
在许多C实现中,指针是内存中的简单地址,
int*
和char*
具有相同的表示形式,编译器将允许为%s
转换传递int*
。在这种情况下,printf
接收它期望的地址,并将在a1
中打印字符串。这就是为什么你观察了你所做的结果。C标准不要求这种行为。因为printf
是标准C库的一部分,所以C标准允许编译器在使用外部链接调用时对其进行特殊处理。假设编译器可以将参数视为具有正确的类型(即使它没有),并将printf
调用更改为使用ptr
的循环,就像它是char*
一样。我不知道有哪种编译器会在这种情况下生成不需要的代码,但关键是C标准并没有禁止它。
指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。 如果一个指针指向的是另外一个指针,我们就称它为 二级指针,或者 指向指针的指针。 假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示: 将这种关系转换为C语言代码: 指针变
6. 指向指针的指针与指针数组 指针可以指向基本类型,也可以指向复合类型,因此也可以指向另外一个指针变量,称为指向指针的指针。 int i; int *pi = &i; int **ppi = π 这样定义之后,表达式*ppi取pi的值,表达式**ppi取i的值。请读者自己画图理解i、pi、ppi这三个变量之间的关系。 很自然地,也可以定义指向“指向指针的指针”的指针,但是很少用到: int
问题内容: 我是Java菜鸟。我已经掌握了将C / C ++指针转换为Java引用的概念,并且进展相当顺利。 我打了一段有指针的代码(即* ptr)。我需要取消引用指针并更改其指向的指针的值(即 ptr =&newthing;) 在Java中这似乎要困难得多。是否有人对如何解决此问题有任何想法?快速谷歌搜索什么都没有。 这是C ++中的代码示例。我想在Java中获得类似的工作,但是ptr_to_p
本文向大家介绍什么是指向指针的指针? 相关面试题,主要包含被问及什么是指向指针的指针? 时的应答技巧和注意事项,需要的朋友参考一下 指针指向的变量是一个指针,即具体内容为一个指针的值,是一个地址. 此时指针指向的变量长度也是4位.
Go 指针 如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。 当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址: Go 指针
我正在学习链表,以及如何在C中使用结构和指针创建链表。下面我举一个例子。据我所知,被调用的将头节点所在的结构的开始内存位置作为参数传递。push()函数的参数将结构节点作为指向指针的指针,因此它作为引用传递,而不是实际副本。因此,我们的的第一个指针只是指向头部节点的内存位置的指针,第二个指针指向该值,该值是头部节点指向的下一个内存位置。我们通过为结构节点分配一些内存,在结构节点内创建一个名为new