Zar*_*uta 1 c arrays string pointers
据我所知,当我们创建数组或字符串时,它们的名称是指向其第一个元素的指针。在这种情况下,指针无法更改。
然而,这段代码可以工作:
#include <stdio.h>
void swapString(char **str1_ptr, char **str2_ptr)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
int main()
{
char strings[][30] = {"Test1","Test2","Test3"};
int i;
swapString((char **)&strings[0],(char **)&strings[1]);
for(i=0;i<3;i++){
printf("%s\n",strings[i]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么这个效果很好?以这种方式交换字符串(或一般的数组)是一个好习惯吗?什么时候使用这种方法不是一个好主意?
\n\n为什么这个效果很好?
\n
它不能很好地工作。\n它似乎工作得很好,因为你对编译器撒了谎并且使用了不足的测试数据。
\nvoid swapString(char **str1_ptr, char **str2_ptr)\n{\n char *temp = *str1_ptr;\n *str1_ptr = *str2_ptr;\n *str2_ptr = temp;\n}\nRun Code Online (Sandbox Code Playgroud)\n您声称提供了一个指向指针的指针。因此,该函数在两个位置之间交换的字节数与指针所占用的字节数一样多。在大多数系统上,这是 4 或 8 个字节。
\n但随后您传递数组的地址,而不是指向指针的指针:
\n char strings[][30] = {"Test1","Test2","Test3"};\n \n swapString((char **)&strings[0],(char **)&strings[1]);\nRun Code Online (Sandbox Code Playgroud)\n这会导致未定义的行为。您正在使用强制转换,因为编译器告诉您,如果删除它们,这就是螃蟹:
\ntest.c:15:28: warning: passing argument 2 of \xe2\x80\x98swapString\xe2\x80\x99 from incompatible pointer type [-Wincompatible-pointer-types]\n 15 | swapString(&strings[0],&strings[1]);\n | ^~~~~~~~~~~\n | |\n | char (*)[30]\ntest.c:3:41: note: expected \xe2\x80\x98char **\xe2\x80\x99 but argument is of type \xe2\x80\x98char (*)[30]\xe2\x80\x99\nRun Code Online (Sandbox Code Playgroud)\n因此,该函数认为它交换了一个指针,但实际上它交换了数组的前 8 个字节。
\n要验证这一点,您可以使用更长的字符串:
\ntest.c:15:28: warning: passing argument 2 of \xe2\x80\x98swapString\xe2\x80\x99 from incompatible pointer type [-Wincompatible-pointer-types]\n 15 | swapString(&strings[0],&strings[1]);\n | ^~~~~~~~~~~\n | |\n | char (*)[30]\ntest.c:3:41: note: expected \xe2\x80\x98char **\xe2\x80\x99 but argument is of type \xe2\x80\x98char (*)[30]\xe2\x80\x99\nRun Code Online (Sandbox Code Playgroud)\n然后你就会得到你应得的结果。;)
\nTest$ ./test\nTest222211\nTest111122\nTest333333\nRun Code Online (Sandbox Code Playgroud)\n如果是 32 位地址,您需要使字符串的前 4 个字节可区分。
\n正如您所看到的,根本没有交换指针。只是你的数组的开头就被搞乱了。
\n如果您想通过交换指针来交换字符串,则需要更改数组定义:
\n#include <stdio.h>\n\nvoid swapString(char **str1_ptr, char **str2_ptr)\n{\n char *temp = *str1_ptr;\n *str1_ptr = *str2_ptr;\n *str2_ptr = temp;\n}\n\nint main()\n{\n char strings[][30] = {"Test111111","Test222222","Test333333"};\n int i;\n\n swapString((char **)&strings[0],(char **)&strings[1]);\n\n for(i=0;i<3;i++){\n printf("%s\\n",strings[i]);\n }\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n作为副作用,您还可以从函数调用中删除强制转换,因为类型现在符合预期。
\n