交换两个字符串指针
我必须在 C 中使用 char[],并且我想通过仅交换指针来在它们之间交换 到数组而不是一次一个字符,所以我写了这段代码:
#include <stdio.h>
void fastSwap (char **i, char **d)
{
char *t = *d;
*d = *i;
*i = t;
}
int main ()
{
char num1[] = "012345678910";
char num2[] = "abcdefghujk";
fastSwap ((char**)&num1,(char**)&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
我得到这个输出(注意最后 4 个字符)
abcdefgh8910 01234567ujk
当我期望时:
abcdefghujk 012345678910
注意:我正在 64 位 Linux 系统上工作。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
您无法修改
num1
和num2
的地址,如果您的测试是:You can't modify the addresses of
num1
andnum2
, your code should work if your test was instead:数组不是指针。虽然当您调用
fastSwap()
时它们会衰减为指针,但这些指针并不是实际的数组。您需要演员这一事实应该会暗示您出现了问题。这会起作用:
Arrays are not pointers. While they decay to pointers when you call your
fastSwap()
, these pointers are not the actual arrays. The fact that you need a cast should give you a hint that something is wrong.This would work:
这将起作用:
This will work:
num1
是一个数组,&num1
是数组本身的地址 - 它不是地址的一个指针。数组本身的地址与数组第一个元素的地址在内存中的位置相同,但类型不同。当您将该地址转换为
char **
时,您声称它指向char *
值 - 但事实并非如此。它指向 13 个字符的块。然后,您的交换函数会像访问char *
一样访问该 13 个字符的数组 - 因为后者的大小与您平台上的 8char
相同,因此您最终会得到交换每个数组的前 8 个字符。num1
is an array, and&num1
is the address of the array itself - it is not an address of a pointer.The address of an array itself is the same location in memory as the address of the first element of the array, but it has a different type. When you cast that address to
char **
, you are claiming that it points at achar *
value - but it does not. It points at a block of 13 chars. Your swap function then accesses that array of 13 chars as if it were achar *
- since the latter is the same size as 8char
s on your platform, you end up swapping the first 8 chars of each array.你的 fastSwap 似乎只能工作。您通过将 '&num1' 和 '&num2' (指向 num1 和 num2 的字符的指针)转换为指向字符 (char**) 的指针来调用未定义的行为。
t 将指向 d 的内容所指向的任何内容,但是 d 指向 num2 的实际字符(“abcdefghujk”或 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00)。这意味着“*d”实际上是复制“num2”的内容,而不是您可能期望的指向 num2 的指针。
't' then 是一个坏指针,但是因为它永远不会被取消引用,所以您可以避免崩溃/段错误。
因为您使用的是 64 位机器/操作系统指针是 8 个字节,所以“t”的值现在是“num2”的前 8 个字节,这就是之后放入 num1 的内容
如果您打算交换指针,则必须首先创建像 Mark 那样的指针变量
或者像 sb1/Karl 那样将 num1 和 num2 更改为指针 (char *) 而不是数组 (char[])
Your fastSwap only seems to work. You're invoking undefined behavior by casting '&num1' and '&num2' (which are pointers to the characters of num1 and num2) to pointers to pointers of characters (char**).
t will point to whatever d's contents are pointing to, however d is pointing to the actually characters of num2 ("abcdefghujk" or 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00). This means that '*d' is actually copying the contents of 'num2' and not the pointer to num2 as you probably expected.
't' then is a bad pointer however since it is never dereferenced you avoid a crash/segment fault.
Because you're on a 64 bit machine/OS pointers are 8 bytes the value of 't' is now the first 8 bytes of 'num2' and this is what gets put into num1 after
If you intend to swap pointers you must first create pointer variables as Mark did
Or change num1 and num2 into pointers (char *) rather than arrays (char[]) as sb1/Karl did
我也遇到过同样的情况,并用以下技巧解决了它:
ps windows platform,vs-2012
I've had the same situation and solved it with the following trick:
p.s. windows platform, vs-2012
将fastSwap改为:
然后调用fastSwap(num1,num2);
Change fastSwap to:
then call fastSwap (num1, num2);
虽然给出的答案已经展示了如何正确执行(并暗示未定义的行为),但您仍然可能对细节感兴趣......
首先,您必须使用字符数组。应用 addressof 运算符不会给你一个指向指针的指针,而是一个指向数组的指针:
语法可能看起来很奇怪,但这就是 C。现在重要的是:你有一个具有一级间接寻址的指针。但是您将其转换为具有两级间接寻址的指针 (
char**
)。现在
fastSwap
中发生的情况是:这会将
*d
的字节复制到t
中,因为系统上的指针有大小。唯一:实际上,您没有指向指针的指针,而是指向仅已转换的数组的指针。因此 array 的前sizeof(void*)
字节将被复制到 t 中。对于其他作业也类似,解释你得到的结果。如果现在你的数组比指针的大小短,那么数组后面的内存将被读取:
将在你的系统上打印(因为指针大小为8字节):
说明:
请注意,你无法保证这样的结果,这只是最有可能的结果。您调用了未定义的行为,任何事情都可能发生,您甚至可能会意外关闭太阳(如果您的编译器碰巧生成了适当的代码......)。
While given answers already showed how to do it right (and hinted to undefined behaviour), you still might be interested in the details...
At very first, you have to character arrays. Applying the addressof operator to won't give you a pointer to pointer, but a pointer to array:
Syntax might look strange, but that's C. The important thing here now is: You have a pointer with one level of indirection. But you cast it to a pointer with two levels of indirection (
char**
).What now happens in
fastSwap
is:This will copy as many bytes of
*d
intot
as pointers on your system have size. Solely: In reality, you do not have a pointer to pointer, but a pointer to array which only has been casted. So the firstsizeof(void*)
bytes of the array will be copied into t. Similarly for the other assignments, explaining the results you get.If now your arrays were shorter than the size of pointers, then memory after the arrays would have been read:
would have printed on your system (as pointer size is 8 bytes):
Explanation:
Be aware that you don't have guarantee for such result, it is just the most likely one. You invoked undefined behaviour, anything might happen instead, you even might switch off the sun by accident (if your compiler happened to produce the appropriate code...).