1

"str"当您使用or&"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;
}
4

2 回答 2

3

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

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

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

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

编辑

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

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

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

char s = **&"str";   // or s = *(&"str")[0]
于 2012-04-08T23:54:38.520 回答
1

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

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

  • 当它是一元运算符的操作数时sizeofsizeof "str"产生数组的大小,而不是指针的大小)。
  • 当它是一元运算符的操作数时&&"str"产生 type 的结果char(*)[4], not char*)。
  • 当它是用于初始化数组对象的初始化程序中的字符串文字时(此处不适用)。

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

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

所以:

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

"str"被隐式转换为一个char*值,指向's'"str"

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

如上所述"str", in"str"[0]衰减char*为 。 "str"[0"产生一个char*值,指向's'. 所以"str""str"[0]具有相同的类型和价值。

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

在这里,由于"str"是 的操作数&,因此不会发生衰减,因此&"str"产生匿名char[4]对象的地址,而不是其第一个字符的地址。这个表达式的类型是char(*)[4],或“指向 4 个字符数组的指针”。

表达式&"str"[0]&"str"两者都产生指针值,它们都指向内存中的同一位置,但它们的类型不同。

在所有三种情况下,计算表达式的结果都作为参数传递给printf. printf使用"%p"格式需要类型的参数void*。在前两种情况下,您传递了 achar*和语言的要求,char*void*暗示它将按预期工作。char*在第三种情况下, vs.没有这样的规则char(*)[4],所以

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

未定义。

碰巧的是,在大多数实现中,所有指针类型都具有相同的大小和表示形式,因此您可以将任意类型的指针传递给printfwith "%p"

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

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

您问题的第二部分涉及一个不同的问题;它是关于指向函数的指针。指针类型表达式的规则与数组类型的规则类似:函数类型的表达式(例如函数名)被隐式转换为指向函数的指针,除非它是sizeof(这是非法的) 或&(这会产生函数的地址)。这就是为什么应用*or&到一个函数就像一个无操作一样。在*func中,func首先衰减为指向函数的指针,*解除对指针的引用,结果再次衰减为指向函数的指针。在&func中,&抑制了衰减,但它产生了指向函数func本身会产生的相同指针。

于 2012-04-09T01:09:27.347 回答