我对指针感到困惑。这是交换两个名称的代码。请参阅代码。考虑输入:hellohai(对于d)和asd(对于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;
}
答案 0 :(得分:3)
执行此操作时:
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'ed缓冲区。
答案 1 :(得分:3)
当你交换指针时,你交换的是指针变量中的内存位置。 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
中的警告。
答案 2 :(得分:0)
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] =&#39; 1&#39 ;; //这是正确的,可以重写。不要把它与字符串文字混淆
为了安全起见 -
1.不要投出malloc
的结果。
2.这些scanf
应该是 -
scanf("%9s",d);
scanf("%4s",e);
为了防止您输入更多9
或4
的字符,这将导致 UB
3. free
你分配的内存。
答案 3 :(得分:0)
发生的事情是你{{}}了两个内存块。这些块具有地址,malloc
和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);
现在,当您在指针之间进行交换时,您所做的只是更改内存块引用,而不是实际的指针地址(无法执行> STRONG>)。
您可以通过在交换之后放置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'
当你使用malloc时,你的计算机会在{strong> 5 的地址Values : | - | - | - | | | |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
提供阻止地址 6 的阻止d
,所以现在它看起来像像这样:
e
读完字符串后, 5 和 6 的块的内容将被写入:
Values : | 5 | 6 | - | | | |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
当您打印Values : | 5 | 6 | - | | hellohai | asd |
Variable : | d | e | f | | | |
Memory(hex): | 1 | 2 | 3 | 4 | 5 | 6 |
时,它会访问它指向的内存地址(在这种情况下为 5 )并打印内容。 d
变量也是如此。
现在,当您交换值时:
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
指向{{1}用于点的。 重要的是要注意,地址 5 和 6的实际值从未被触及。
当你这样做时:
d
您告诉计算机访问地址 5 的内存块内容的第一个字节并进行更改。所以现在你有了:
e
这是一个非常简单的表示你的记忆可能是什么样子,所以你可以了解它的工作原理。