我必须在C中使用char []并且我想通过仅交换指针来交换它们 到数组而不是一次只有一个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系统。
答案 0 :(得分:12)
您无法修改num1
和num2
的地址,如果您的测试相反,您的代码应该有效:
int main ()
{
char num1[] = "012345678910";
char num2[] = "abcdefghujk";
char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
printf ("%s\n",test1);
printf ("%s\n",test2);
return 0;
}
答案 1 :(得分:7)
数组不是指针。当你调用fastSwap()
时它们会衰减到指针,这些指针不是实际的数组。你需要演员表的事实应该给你一个错误的暗示。
这样可行:
void fastSwap (const char **i, const char **d)
{
const char *t = *d;
*d = *i;
*i = t;
}
const char* num1 = "012345678910";
const char* num2 = "abcdefghujk";
fastSwap (&num1,&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
答案 2 :(得分:5)
这将有效:
int main ()
{
char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
答案 3 :(得分:4)
num1
是一个数组,&num1
是数组本身的地址 - 不是指针的地址。< / p>
数组本身的地址与内存中的第一个元素的地址位置相同,但它的类型不同。当您将该地址转换为char **
时,您声称其指向char *
值 - 但事实并非如此。它指向一个13个字符的块。然后你的交换函数访问13个字符的数组,好像它是char *
- 因为后者与平台上的8 char
大小相同,你最终交换每个字符的前8个字符阵列。
答案 4 :(得分:3)
你的fastSwap似乎才有用。您通过将'&amp; num1'和'&amp; num2'(指向num1和num2的字符的指针)转换为指向字符指针(char **)的指针来调用未定义的行为。
char *t = *d
t将指向任何内容指向的内容,但是d指向num2的实际字符(“abcdefghujk”或0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00)。这意味着'* d'实际上正在复制'num2'的内容,而不是像你预期的那样复制指向num2的指针。
然后't'是一个坏指针,因为它永远不会被解除引用,你可以避免崩溃/段错误。
因为你在64位机器上/操作系统指针是8字节,'t'的值现在是'num2'的前8个字节,这是在
后放入num1的内容*i = t
如果你打算交换指针,你必须首先创建指针变量,如Mark所做的那样
char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
或者将num1和num2更改为指针(char *)而不是数组(char []),如sb1 / Karl所做的那样
char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
答案 5 :(得分:1)
我遇到了同样的情况并通过以下技巧解决了这个问题:
P.S。 Windows平台,vs-2012
void FastSwap (void **var1, void **var2) {
void *pTmp = *var1;
*var1 = *var2;
*var2 = pTmp;
}
int main () {
char *s1 = "1234567890123456";
char *s2 = "abcdefghij";
printf ("s1 before swap: \"%s\"\n", s1);
printf ("s2 before swap: \"%s\"\n", s2);
// if you change arguments in the FastSwap definition as (char **)
// then you can erase the (void **) part on the line below.
FastSwap ((void **) &s1, (void **) &s2);
printf ("s1 after swap : \"%s\"\n", s1);
printf ("s2 after swap : \"%s\"\n", s2);
return (0);
}
答案 6 :(得分:0)
将fastSwap更改为:
void fastSwap (char *i, char *d)
{
while ((*i) && (*d))
{
char t = *d;
*d = *i;
*i = t;
i ++;
d ++;
}
}
然后调用fastSwap(num1,num2);
答案 7 :(得分:0)
int swap(char *a, char *b){
char *temp = (char *)malloc((strlen(a) + 1)*sizeof(char));
strcpy(temp, a);
strcpy(a, b);
strcpy(b, temp);
}
int main(){
char a[10] = "stack";
char b[10] = "overflow";
swap(a, b);
printf("%s %s", a, b);
}
答案 8 :(得分:0)
尽管给出的答案已经显示了正确的操作方法(并提示行为未定义),但您仍然可能对详细信息感兴趣...
首先,您必须使用字符数组。将addressof运算符应用于不会提供指向指针的指针,而是指向数组的指针:
int(*ptr1)[10] = &num1;
语法可能看起来很奇怪,但这就是C。现在这里重要的是:您的指针具有一个间接级别。但是您将其强制转换为具有两个间接级别(char**
)的指针。
fastSwap
中现在发生的是:
char* t = *d;
这会将*d
的字节复制到t
中,这取决于系统上的指针大小。唯一的:实际上,您没有指向指针的指针,而是只有已强制转换的指向数组的指针。因此,数组的前sizeof(void*)
个字节将被复制到t中。类似地,对于其他作业,说明您得到的结果。
如果现在您的数组小于指针的大小,则将读取数组之后的内存:
int a[] = "123";
int b[] = "456";
int c[] = "789";
fastSwap ((char**)&a, char**(&b));
printf("%s %s %s", a, b, c);
将在您的 系统上打印(指针大小为8个字节):
456 789 456
说明:
char *t = *d;
// copied the four bytes of b into t - AND the next four bytes (those of c!!!)
*d = *i;
// copied the eight bytes of a AND b int b AND c
// b contains "123", c "456"
*i = t;
// copied the eight bytes that were copied from b and c into a and b
// the "123" in b now got overwritten, that's why you never see them...
请注意,您无法保证获得这种结果,这只是最有可能的结果。您调用了未定义的行为,可能发生任何事情,甚至可能偶然关闭了太阳(如果您的编译器碰巧产生了适当的代码...)。