当前位置: 首页 > 知识库问答 >
问题:

指向int的指针==指向char的指针(多少)?

戚建华
2023-03-14

在下面给出的代码中,我声明了一个指向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;
}

共有2个答案

张翰海
2023-03-14

为什么是printf(“%s”,ptr);这是完全正确的

事实并非如此——它可能会像预期的那样工作,但不能保证一定会成功。通过将错误类型的参数传递给printf,您调用了未定义的行为,这意味着编译器不需要以任何特定方式处理这种情况。您可能会得到预期的输出,您可能会得到垃圾输出,您可能会得到运行时错误,您可能会破坏系统的状态,您可能会在宇宙的另一端打开一个黑洞。

路思源
2023-03-14

首先考虑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 = &pi; 这样定义之后,表达式*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