如果我有一个指向char * s数组的指针,换句话说,就是一个名为p1的char **,那么我做(char *)p1会得到什么?我猜这会损失一些精度。我会丢失什么信息,而p1现在会指向什么?谢谢!
答案 0 :(得分:5)
如果您询问将int **
转换为int *
的问题,答案将有所不同。首先,让我们考虑一下,因为我怀疑它更能代表您要提出的问题,而char *
案则更为复杂,因为其中涉及特殊目的。
假设您有多个int
:int a, b, c, d;
。您可以建立指向它们的指针数组:int *p[] = { &a, &b, &c, &d };
。您也可以指向以下指针之一:int **q = &p[1];
。现在q
指向p[1]
,其中包含地址b
。
在编写*q
时,编译器知道q
指向指向int
的指针,因此它知道*q
指向int
的指针。如果您编写**q
,则编译器在知道*q
指向int
的情况下,将从内存中获取*q
并将其用作获取{{1} }。
如果将int
转换为q
并尝试使用它,如int *
,会发生什么?当您将printf("%d\n", * (int *) q);
转换为q
时,您(错误地)告诉编译器将其视为指向int *
的指针。然后,int
告诉编译器转到该地址并获得一个* (int *) q
。
这是无效的代码-C标准未定义其行为。具体而言,它违反了C 2018 6.5 7,即说只能通过具有正确类型的左值表达式访问对象,该左值表达式具有与实际对象兼容的类型或某些其他情况,在此均不适用。在int
所指向的位置,有一个指向q
的指针,但是您试图像访问int
一样访问它,这是不允许的。
现在让我们考虑一下int
至char **
的情况。和以前一样,您可以使用一些char *
并将其转换为char **q
。现在,您要告诉编译器转到char *
指向的位置,那里有一个指向q
的指针,并像访问char
那样访问该内存位置。
C对于这种情况有特殊的规则。您允许 通过通过char
访问组成对象的字节来检查它们。因此,如果将char *
转换为char **
并使用它,如char *
中那样,结果将是组成指针的第一个(最低寻址)字节。您甚至可以使用以下代码查看其余字节:
* (char *) q
此代码将向您显示组成char *t = (char *) q;
printf("%d\n", t[0]);
printf("%d\n", t[1]);
printf("%d\n", t[2]);
printf("%d\n", t[3]);
的指针的前四个字节的十进制值,该指针位于char
指定的位置。
总而言之,将q
转换为char **
将使您可以检查代表char *
的字节。但是,通常,不应将一个间接级别的指针转换为另一种间接级别的指针。
答案 1 :(得分:1)
当我将指针视为内存地址而不是某些抽象的高级对象时,我发现指针更有意义。
所以char **是一个指向一个字符的内存地址,一个指向字符的内存地址。
0x0020 -> 0x0010 -> 0x0041 'A'
在投射时,您更改的是数据解释,而不是实际数据。所以char *是
0x0020 -> 0x0010 (unprintable)
这几乎毫无用处。将此随机数据解释为以空终止的字符串可能会造成灾难性的后果。