[英]Swapping names(malloced ones) using non malloced pointer variable
I am getting confused with pointers.我对指针感到困惑。 Here is a code to swap two names.
这是一个交换两个名字的代码。 Please see the code.
请看代码。 Consider Input : hellohai(for d) and asd(for e).
考虑输入:hellohai(for d) 和 asd(for e)。 Output i am getting : asd 1ellohai 1ellohai
我得到的输出:asd 1ellohai 1ellohai
#include<stdio.h>
#include<stdlib.h>
int main()
{
char *d,*e,*f;
d=(char*)malloc(10);
e=(char*)malloc(5);
scanf("%s",d);
scanf("%s",e);
f=d;
d=e;
e=f; //while printing e it prints the whole value contained in f (i.e.1ellohai). How? size of e is 5 only
f[0]='1'; // f is in read-only memory. So this should fail?
printf("%s \t %s \t %s \n",d,e,f);
return 0;
}
When you do this:当你这样做时:
d=(char*)malloc(10);
e=(char*)malloc(5);
d
points to a 10 byte buffer, and e
points to a 5 byte buffer. d
指向一个 10 字节的缓冲区,而e
指向一个 5 字节的缓冲区。
Then you have this:然后你有这个:
f=d; // f now points to the 10 byte buffer
d=e; // d now points to the 5 byte buffer
e=f; // e now points to the 10 byte buffer
You're not actually copying the strings from one to the other.您实际上并没有将字符串从一个复制到另一个。 You're really changing the pointers.
你真的在改变指针。
Then when you do this:然后当你这样做时:
f[0]='1';
It changes the first byte of the 10 byte buffer.它更改 10 字节缓冲区的第一个字节。
f
is not read-only because it is pointing to the same malloc'ed buffer that d
originally (and now e
) pointed to. f
不是只读的,因为它指向d
最初(现在是e
)指向的同一个 malloc 缓冲区。
When you are swapping pointers what you are swapping is the memory location that is in the pointer variable.当您交换指针时,您交换的是指针变量中的内存位置。
f
has the old value of d
and is pointing to the memory allocated via malloc
. f
具有d
的旧值,并指向通过malloc
分配的malloc
。 Therefore所以
f[0]='1'; // f is in read-only memory. So this should fail?
Is incorrect.是不正确的。
Second to explain the output.其次解释输出。 Before you swap you basically have
d
pointing to a string containing "hellohai"
and e
pointing to a string containing "asd"
.在你交换之前,你基本上有
d
指向一个包含"hellohai"
的字符串和e
指向一个包含"asd"
的字符串。 After the swap f
and e
point to a string containing "hellohai"
and d
points to a string containing "asd"
.交换后
f
和e
指向包含"hellohai"
的字符串, d
指向包含"asd"
的字符串。 You then modifying the string that f
and e
are pointing to through f
so the now that is "1ellohai"
.然后修改
f
和e
通过f
指向的字符串,所以现在是"1ellohai"
。 You then print everything, and the output is as expected.然后打印所有内容,输出符合预期。
Memory allocated by malloc
is writable. malloc
分配的malloc
是可写的。 What you are probably confusing this with is the following:您可能对此感到困惑的是以下内容:
char *f = "hello";
f[0] = '1';
This is a bad idea and leads to undefined behavior.这是一个坏主意,会导致未定义的行为。
Finally, as a caveat in C it is generally not a good idea to cast the result of malloc
.最后,作为 C 中的一个警告,
malloc
的结果通常不是一个好主意。
d=(char*)malloc(10); //buffer for 10 chars
e=(char*)malloc(5); //buffer for 5 chars
These are not size of pointers d
and e
(You should see their size using sizeof
operator.).这些不是指针
d
和e
的大小(您应该使用sizeof
运算符查看它们的大小。)。
The only thing that change is that what these points to .唯一改变的是这些指向的内容。 These
这些
f=d;
d=e;
e=f;
actually don't copy string's .实际上不要复制字符串的 . This just changes to what the pointers point.
这只是改变了指针指向的内容。 f[0]='1';
f[0]='1'; // This is correct and is re-writable .
// 这是正确的并且是可重写的。 Don't confuse it with string literal
不要将它与字符串文字混淆
For some safety -为了一些安全 -
1.Don't cast result of malloc
. 1.不要转换
malloc
结果。
2.These scanf
's shoud be - 2.这些
scanf
应该是 -
scanf("%9s",d);
scanf("%4s",e);
as to prevent case when you enter chars more that 9
or 4
which will casue UB为了防止输入超过
9
或4
字符时出现UB 的情况
3. free
the memory you allocate . 3.
free
你分配的内存。
What is happening is that you're malloc
ing two memory blocks.发生的事情是您正在
malloc
两个内存块。 Those blocks have address, which d
and e
holds.这些块有地址,
d
和e
持有。 To confirm that, put these after your scanf
s.要确认这一点,请将它们放在您的
scanf
之后。
printf ("Address of d: %p\n", &d);
printf ("Address of e: %p\n", &e);
printf ("Address of block d(value of d): %p\n", d);
printf ("Address of block e(value of e): %p\n", e);
My output is:我的输出是:
Address of d: 0x7fff037a5488
Address of e: 0x7fff037a5490
Address of block d(value of d): 0xa8e010
Address of block e(value of e): 0xa8e030
Now, when you make the swap between the pointers, all you're doing is changing the memory block references , not the actual pointer address (which you can't do ).现在,当您在指针之间进行交换时,您所做的只是更改内存块引用,而不是实际的指针地址(您不能这样做)。
You can confirm that by putting those printf
after the swaps, like this:您可以通过将这些
printf
放在交换之后来确认,如下所示:
#include<stdio.h>
#include<stdlib.h>
int main()
{
char *d,*e,*f;
d=(char*)malloc(10);
e=(char*)malloc(5);
scanf("%s",d);
scanf("%s",e);
printf ("Address of d: %p\n", &d);
printf ("Address of e: %p\n", &e);
printf ("Address of f: %p\n", &f);
printf ("Address of block d(value of d): %p\n", d);
printf ("Address of block e(value of e): %p\n", e);
f=d;
d=e;
e=f; //while printing e it prints the whole value contained in f (i.e.1ellohai). How? size of e is 5 only
printf ("Address of d: %p\n", &d);
printf ("Address of e: %p\n", &e);
printf ("Address of f: %p\n", &f);
printf ("Address of block d(value of d): %p\n", d);
printf ("Address of block e(value of e): %p\n", e);
printf ("Address of block f(value of f): %p\n", f);
f[0]='1'; // f is in read-only memory. So this should fail?
printf("%s \t %s \t %s \n",d,e,f);
return 0;
}
And the output:和输出:
$ ./draft
hellohai
asd
Address of d: 0x7ffebae87d78
Address of e: 0x7ffebae87d80
Address of f: 0x7ffebae87d88
Address of block d(value of d): 0x2143010
Address of block e(value of e): 0x2143030
Address of d: 0x7ffebae87d78
Address of e: 0x7ffebae87d80
Address of f: 0x7ffebae87d88
Address of block d(value of d): 0x2143030
Address of block e(value of e): 0x2143010
Address of block f(value of f): 0x2143010
asd 1ellohai 1ellohai
From this you can see that:从中你可以看出:
e
and f
point to the same memory block. e
和f
指向同一个内存块。 That's why doing f[0]='1'
changes the value printed by both.f[0]='1'
改变两者打印的值。After you declare your variables, you memory will look like this:声明变量后,您的内存将如下所示:
Values : | - | - | - | | | |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
When you malloc, your computer gives d
the block at address 5 and e
the block at address 6 , so now it looks like this:当你 malloc 时,你的计算机给了
d
地址5的块和e
地址6的块,所以现在它看起来像这样:
Values : | 5 | 6 | - | | | |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
After you read your strings, the contents of the blocks at 5 and 6 will get written:读取字符串后,将写入5和6块的内容:
Values : | 5 | 6 | - | | hellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
When you print d
, it access the memory address it points to ( 5 in this case) and print the contents.当您打印
d
,它会访问它指向的内存地址(在本例中为5 )并打印内容。 Same for the e
variable. e
变量相同。
Now, when you swap the values doing:现在,当您交换值时:
f=d;
Values : | 5 | 6 | 5 | | hellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
d=e;
Values : | 6 | 6 | 5 | | hellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
e=f;
Values : | 6 | 5 | 5 | | hellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
Now e
and f
point to the same place (where d
used to point) and d
points to where e
used to point.现在
e
和f
指向同一个地方( d
曾经指向的地方), d
指向e
曾经指向的地方。 It's important to note that the actual values of the addresses 5 and 6 never got touched .重要的是要注意地址5和6的实际值从未被触及。
And when you do:当你这样做时:
f[0]='1';
You're telling the computer to access the first byte of the contents of the memory block at address 5 and change it.您告诉计算机访问地址5处内存块内容的第一个字节并更改它。 So now you have:
所以现在你有:
Values : | 6 | 5 | 5 | | 1ellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
This is a very simple representation of what you memory might look like so you can get the idea of how it works.这是一个非常简单的表示您的内存可能是什么样子的,因此您可以了解它是如何工作的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.