可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
i have to char[] in C and i wanted to swap between them, by only swaping the pointer
to the array and not one char at a time so i wrote this code:
#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;
}
I get this output (note the last 4 characters)
abcdefgh8910
01234567ujk
When I expect:
abcdefghujk
012345678910
NOTE: I am working on a 64 bit Linux System.
回答1:
You can't modify the addresses of num1
and num2
, your code should work if your test was instead:
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;
}
回答2:
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:
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);
回答3:
This will work:
int main ()
{
char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
回答4:
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 a char *
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 a char *
- since the latter is the same size as 8 char
s on your platform, you end up swapping the first 8 chars of each array.
回答5:
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**).
char *t = *d
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
*i = t
If you intend to swap pointers you must first create pointer variables as Mark did
char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
Or change num1 and num2 into pointers (char *) rather than arrays (char[]) as sb1/Karl did
char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
回答6:
I've had the same situation and solved it with the following trick:
p.s. windows platform, 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);
}
回答7:
Change fastSwap to:
void fastSwap (char *i, char *d)
{
while ((*i) && (*d))
{
char t = *d;
*d = *i;
*i = t;
i ++;
d ++;
}
}
then call fastSwap (num1, num2);
回答8:
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);
}
回答9:
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:
int(*ptr1)[10] = &num1;
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:
char* t = *d;
This will copy as many bytes of *d
into t
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 first sizeof(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:
int a[] = "123";
int b[] = "456";
int c[] = "789";
fastSwap ((char**)&a, char**(&b));
printf("%s %s %s", a, b, c);
would have printed on your system (as pointer size is 8 bytes):
456 789 456
Explanation:
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...
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...).