如何使同一个指针有不同的类型?

时间:2012-04-08 23:41:02

标签: c

当你采用"str"&"str"[0]&"str"并获得相同的指针但不同的类型时,你可以看到我的意思。

注意:我在一个字符串文字不相同的系统上。

printf("%p\n", "str");
printf("%p\n", &"str"[0]);
printf("%p\n", &"str");

// hypothetical output:
// 0xADD12E550  (ptr to char)
// 0xADD12E550  (ptr to char)
// 0xADD12E550  (ptr to arr of char)

所以理论上,当我解除引用&"str"时,我应该能够获取字符串的第一个字符,因为我正在取消引用相同的指针。特别是,情况并非如此,我必须两次取消引用。一旦获得数组,然后再次获得第一个字符常量:

// &"str" = 0xADD12E550
// *(0xADD12E550) = 0xADD12E550
// *(0xADD12E550) = 's'

// **(&"str") == 's'

也许这个问题也可以回答这是可能的:

#include <stdio.h>

void dafunk() {
  printf("dadftendirekt\n");
}

main() {
  void (*dafunkptr)() = dafunk;
  (***************dafunkptr)();

  return 0;
}

2 个答案:

答案 0 :(得分:3)

对象"str"的类型为char的数组4。

"str"的值是char的指针类型。

&"str"[0]的值是char的指针类型。

&"str"的值是指向char的数组4的类型指针。

修改

现在要访问例如字符串的第一个字符,从"str"开始,您必须取消引用该表达式:

char s = *"str";  // or s = "str"[0] 

或者从表达式&"str"中你必须取消引用表达式两次,因为它的类型是一个指向数组的指针:

char s = **&"str";   // or s = *(&"str")[0]

答案 1 :(得分:1)

表达式"str"的类型为char[4]。 (在C ++中,它将是const char[4]。)

在大多数情况下,任何数组类型的表达式都会隐式转换为指向数组对象的第一个元素的指针。这种转换通常被称为&#34;衰变&#34;。例外情况是:

  • 如果它是一元sizeof运算符的操作数(sizeof "str"产生数组的大小,而不是指针的大小)。
  • 当它是一元&运算符的操作数时,&"str"会产生char(*)[4]类型的结果,而不是char*)。
  • 当用于初始化数组对象的初始值设定项中的字符串文字时(此处不适用)。

在这三种情况下,数组表达式保持其数组类型。

字符串文字是指隐式创建的具有静态存储持续时间的数组对象,其大小足以容纳文字的字符加上终止'\0'空字符。在这种情况下,"str"引用类型为char[4]的匿名静态对象。

所以:

printf("%p\n", "str");

"str"隐式转换为char*值,指向's'的{​​{1}}。

"str"

printf("%p\n", &"str"[0]); 中的"str"衰减到"str"[0],如上所述。 char*生成"str"[0"值,指向char*。因此's'"str"具有相同的类型和价值。

"str"[0]

此处,由于printf("%p\n", &"str"); "str"的操作数,因此衰减不会发生,因此&会产生匿名&"str"对象的地址,而不是第一个字符的地址。此表达式的类型为char[4],或者&#34;指向4 char&#34;的数组的指针。

表达式char(*)[4]&"str"[0]都会产生指针值,两者都指向内存中的相同位置,但它们属于不同类型。

在所有三种情况下,评估表达式的结果都作为参数传递给&"str"printf格式的printf需要"%p"类型的参数。在前两种情况下,您传递了void*,语言对char*char*的要求意味着它将按预期工作。在第三种情况下,void*char*没有此类规则,因此行为

char(*)[4]

未定义。

实际上,在大多数实现中,所有指针类型都具有相同的大小和表示,因此您可以通过printf("%p\n", &"str"); 将任意类型的指针传递给printf

在所有三种情况下,您可以(并且可能应该)将表达式显式地转换为"%p",从而避免未定义的行为:

void*

问题的第二部分涉及一个独特的问题;它是关于函数的指针。指针类型表达式的规则与数组类型的表达式类似:函数类型的表达式(如函数名称)被隐式转换为指向函数的指针,除非它是{{1的操作数(这是非法的)或printf("%p\n", (void*)"str"); printf("%p\n", (void*)&"str"[0]); printf("%p\n", (void*)&"str"); (产生函数的地址)。这就是为什么将sizeof&应用于函数就像无操作一样。在*中,&首先衰减到指向函数的指针,*func取消引用指针,结果再次衰减到指向函数的指针。在func中,*禁止衰减,但它会产生与&func本身产生的函数相同的指针。