将 char** 转换为 char* - 它会改变它指向的内容吗?
Casting char** to char* - Does it change what it points to?
如果我有一个指向 char* 数组的指针,换句话说,一个名为 p1 的 char**,如果我执行 (char*)p1 会得到什么?我猜会有一些精度损失。我会丢失什么信息,p1 现在指向什么?谢谢!
如果您询问过将 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
并将其用作获取 [=14= 的地址].
如果将 q
转换为 int *
并尝试使用它,会发生什么情况,如 printf("%d\n", * (int *) q);
?当您将 q
转换为 int *
时,您(错误地)告诉编译器将其视为指向 int
的指针。然后,* (int *) q
告诉编译器转到该地址并获得 int
.
这是无效代码 — C 标准未定义其行为。具体来说,它违反了 C 2018 6.5 7,其中规定对象只能由具有正确类型的左值表达式访问——要么是与实际对象的类型兼容的类型,要么是某些其他情况,none 其中在这里申请。在 q
指向的地方,有一个指向 int
的指针,但您试图像访问 int
一样访问它,这是不允许的。
现在让我们考虑 char **
到 char *
的情况。和以前一样,您可能需要一些 char **q
并将其转换为 char *
。现在,您要告诉编译器转到 q
点的位置,那里有指向 char
的指针,并像那里有 char
一样访问该内存位置。
C 对这种情况有特殊的规定。您 被 允许通过 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 *
将允许您检查表示 char *
的字节。但是,一般来说,您不应将一个间接级别的指针转换为另一间接级别的指针。
当我将指针视为内存地址而不是一些抽象的高级事物时,我发现指针更有意义。
所以一个char**是一个内存地址,它指向一个字符。
0x0020 -> 0x0010 -> 0x0041 'A'
投射时,您改变了数据的解释,而不是实际数据。所以 char* 是
0x0020 -> 0x0010 (unprintable)
这几乎肯定没有用。将此随机数据解释为空终止字符串可能是灾难性的。
如果我有一个指向 char* 数组的指针,换句话说,一个名为 p1 的 char**,如果我执行 (char*)p1 会得到什么?我猜会有一些精度损失。我会丢失什么信息,p1 现在指向什么?谢谢!
如果您询问过将 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
并将其用作获取 [=14= 的地址].
如果将 q
转换为 int *
并尝试使用它,会发生什么情况,如 printf("%d\n", * (int *) q);
?当您将 q
转换为 int *
时,您(错误地)告诉编译器将其视为指向 int
的指针。然后,* (int *) q
告诉编译器转到该地址并获得 int
.
这是无效代码 — C 标准未定义其行为。具体来说,它违反了 C 2018 6.5 7,其中规定对象只能由具有正确类型的左值表达式访问——要么是与实际对象的类型兼容的类型,要么是某些其他情况,none 其中在这里申请。在 q
指向的地方,有一个指向 int
的指针,但您试图像访问 int
一样访问它,这是不允许的。
现在让我们考虑 char **
到 char *
的情况。和以前一样,您可能需要一些 char **q
并将其转换为 char *
。现在,您要告诉编译器转到 q
点的位置,那里有指向 char
的指针,并像那里有 char
一样访问该内存位置。
C 对这种情况有特殊的规定。您 被 允许通过 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 *
将允许您检查表示 char *
的字节。但是,一般来说,您不应将一个间接级别的指针转换为另一间接级别的指针。
当我将指针视为内存地址而不是一些抽象的高级事物时,我发现指针更有意义。
所以一个char**是一个内存地址,它指向一个字符。
0x0020 -> 0x0010 -> 0x0041 'A'
投射时,您改变了数据的解释,而不是实际数据。所以 char* 是
0x0020 -> 0x0010 (unprintable)
这几乎肯定没有用。将此随机数据解释为空终止字符串可能是灾难性的。