使用非 malloced 指针变量交换名称(malloced 的)
Swapping names(malloced ones) using non malloced pointer variable
我对指针感到困惑。这是交换两个名字的代码。请看代码。考虑输入:hellohai(for d) 和 asd(for e)。
我得到的输出: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;
}
当你这样做时:
d=(char*)malloc(10);
e=(char*)malloc(5);
d
指向 10 字节缓冲区,e
指向 5 字节缓冲区。
那么你有这个:
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
您实际上并没有将字符串从一个复制到另一个。你真的在改变指针。
那么当你这样做的时候:
f[0]='1';
它改变了10字节缓冲区的第一个字节。 f
不是只读的,因为它指向与 d
最初(现在 e
)指向的同一个 malloc 缓冲区。
交换指针时,交换的是指针变量中的内存位置。 f
具有 d
的旧值,并指向通过 malloc
分配的内存。因此
f[0]='1'; // f is in read-only memory. So this should fail?
不正确。
二来解释输出。在交换之前,基本上 d
指向包含 "hellohai"
的字符串,e
指向包含 "asd"
的字符串。交换后 f
和 e
指向包含 "hellohai"
的字符串,而 d
指向包含 "asd"
的字符串。然后修改 f
和 e
通过 f
指向的字符串,所以现在是 "1ellohai"
。然后打印所有内容,输出符合预期。
malloc
分配的内存是可写的。您可能将其与以下内容混淆:
char *f = "hello";
f[0] = '1';
这是个坏主意,会导致未定义的行为。
最后,作为 C 中的警告 it is generally not a good idea to cast the result of malloc
。
d=(char*)malloc(10); //buffer for 10 chars
e=(char*)malloc(5); //buffer for 5 chars
这些不是指针 d
和 e
的大小(您应该使用 sizeof
运算符查看它们的大小。)。
唯一改变的是这些指向的内容。这些
f=d;
d=e;
e=f;
实际上不要复制字符串的 .这只是改变了指针指向的内容。
f[0]='1'; // 这是正确的并且是可重写的。不要将它与字符串文字混淆
为了安全起见-
1.Don未投出 malloc
的结果。
2.These scanf
的应该是-
scanf("%9s",d);
scanf("%4s",e);
为了防止输入的字符多于 9
或 4
会导致 UB
3.free
你分配的内存。
正在发生的事情是您 malloc
ing 了两个内存块。这些块有地址,d
和 e
持有。为确认这一点,请将这些放在 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);
我的输出是:
Address of d: 0x7fff037a5488
Address of e: 0x7fff037a5490
Address of block d(value of d): 0xa8e010
Address of block e(value of e): 0xa8e030
现在,当您在指针之间进行交换时,您所做的只是更改 内存块引用 ,而不是实际的指针地址(您 做不到).
您可以通过将 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;
}
并且输出:
$ ./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
由此可见:
-
- 指针的地址从未改变。
-
- 引用(它们的值)改变了。他们被交换了。
-
e
和f
指向同一个内存块。这就是为什么 f[0]='1'
会改变两者打印的值。
原始内存布局
声明变量后,您的内存将如下所示:
Values : | - | - | - | | | |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
当你 malloc 时,你的计算机给 d
地址 5 的块和 e
地址 6[= 的块101=],所以现在看起来像这样:
Values : | 5 | 6 | - | | | |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
读取字符串后,5 和 6 块的 内容 将被写入:
Values : | 5 | 6 | - | | hellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
当你打印d
时,它会访问它指向的内存地址(在本例中为5)并打印内容。 e
变量也是如此。
现在,当您交换值时:
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 |
现在e
和f
指向同一个地方(其中d
用于点)和d
点到e
习惯的地方。 重要的是要注意地址5和6的实际值永远不会感动了.
当你这样做时:
f[0]='1';
您是在告诉计算机访问地址 5 处内存块内容的第一个字节并更改它。所以现在你有:
Values : | 6 | 5 | 5 | | 1ellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
这是您的记忆可能看起来的一个非常简单的表示,因此您可以了解它是如何工作的。
我对指针感到困惑。这是交换两个名字的代码。请看代码。考虑输入:hellohai(for d) 和 asd(for e)。 我得到的输出: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;
}
当你这样做时:
d=(char*)malloc(10);
e=(char*)malloc(5);
d
指向 10 字节缓冲区,e
指向 5 字节缓冲区。
那么你有这个:
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
您实际上并没有将字符串从一个复制到另一个。你真的在改变指针。
那么当你这样做的时候:
f[0]='1';
它改变了10字节缓冲区的第一个字节。 f
不是只读的,因为它指向与 d
最初(现在 e
)指向的同一个 malloc 缓冲区。
交换指针时,交换的是指针变量中的内存位置。 f
具有 d
的旧值,并指向通过 malloc
分配的内存。因此
f[0]='1'; // f is in read-only memory. So this should fail?
不正确。
二来解释输出。在交换之前,基本上 d
指向包含 "hellohai"
的字符串,e
指向包含 "asd"
的字符串。交换后 f
和 e
指向包含 "hellohai"
的字符串,而 d
指向包含 "asd"
的字符串。然后修改 f
和 e
通过 f
指向的字符串,所以现在是 "1ellohai"
。然后打印所有内容,输出符合预期。
malloc
分配的内存是可写的。您可能将其与以下内容混淆:
char *f = "hello";
f[0] = '1';
这是个坏主意,会导致未定义的行为。
最后,作为 C 中的警告 it is generally not a good idea to cast the result of malloc
。
d=(char*)malloc(10); //buffer for 10 chars
e=(char*)malloc(5); //buffer for 5 chars
这些不是指针 d
和 e
的大小(您应该使用 sizeof
运算符查看它们的大小。)。
唯一改变的是这些指向的内容。这些
f=d;
d=e;
e=f;
实际上不要复制字符串的 .这只是改变了指针指向的内容。 f[0]='1'; // 这是正确的并且是可重写的。不要将它与字符串文字混淆
为了安全起见-
1.Don未投出 malloc
的结果。
2.These scanf
的应该是-
scanf("%9s",d);
scanf("%4s",e);
为了防止输入的字符多于 9
或 4
会导致 UB
3.free
你分配的内存。
正在发生的事情是您 malloc
ing 了两个内存块。这些块有地址,d
和 e
持有。为确认这一点,请将这些放在 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);
我的输出是:
Address of d: 0x7fff037a5488
Address of e: 0x7fff037a5490
Address of block d(value of d): 0xa8e010
Address of block e(value of e): 0xa8e030
现在,当您在指针之间进行交换时,您所做的只是更改 内存块引用 ,而不是实际的指针地址(您 做不到).
您可以通过将 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;
}
并且输出:
$ ./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
由此可见:
-
- 指针的地址从未改变。
-
- 引用(它们的值)改变了。他们被交换了。
-
e
和f
指向同一个内存块。这就是为什么f[0]='1'
会改变两者打印的值。
原始内存布局
声明变量后,您的内存将如下所示:
Values : | - | - | - | | | |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
当你 malloc 时,你的计算机给 d
地址 5 的块和 e
地址 6[= 的块101=],所以现在看起来像这样:
Values : | 5 | 6 | - | | | |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
读取字符串后,5 和 6 块的 内容 将被写入:
Values : | 5 | 6 | - | | hellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
当你打印d
时,它会访问它指向的内存地址(在本例中为5)并打印内容。 e
变量也是如此。
现在,当您交换值时:
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 |
现在e
和f
指向同一个地方(其中d
用于点)和d
点到e
习惯的地方。 重要的是要注意地址5和6的实际值永远不会感动了.
当你这样做时:
f[0]='1';
您是在告诉计算机访问地址 5 处内存块内容的第一个字节并更改它。所以现在你有:
Values : | 6 | 5 | 5 | | 1ellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
这是您的记忆可能看起来的一个非常简单的表示,因此您可以了解它是如何工作的。