使用非malloced指针变量交换名称(malloced的)

时间:2015-09-11 13:34:22

标签: c pointers memory malloc dynamic-allocation

我对指针感到困惑。这是交换两个名称的代码。请参阅代码。考虑输入: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;
}

4 个答案:

答案 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"的字符串。交换fe指向包含"hellohai"d的字符串后,指向包含"asd"的字符串。然后,您通过f修改ef指向的字符串,以便现在为"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 

这些不是指针de的大小(您应该使用sizeof运算符来查看它们的大小。)。

唯一改变的是这些指向的内容。这些

    f=d;
    d=e;   
    e=f;

实际上并不复制字符串。这只是指向指针的变化。     F [0] =&#39; 1&#39 ;; //这是正确的,可以重写。不要把它与字符串文字混淆

为了安全起见 -

1.不要投出malloc的结果。

2.这些scanf应该是 -

    scanf("%9s",d);
    scanf("%4s",e);

为了防止您输入更多94的字符,这将导致 UB

3. free你分配的内存。

答案 3 :(得分:0)

发生的事情是你{{}}了两个内存块。这些块具有地址,mallocd成立。要确认这一点,请将这些内容放在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;
}

从中您可以看到:

    1. 指针的地址从未更改。
    1. 引用(其值)已更改。他们匆匆忙忙。
    1. $ ./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

这是一个非常简单的表示你的记忆可能是什么样子,所以你可以了解它的工作原理。