指针的内存分配适用于固定变量分配的字符串但不适用于用户输入的字符串

Memory allocation of pointer working for fixed variable assigned string but not for user input string

给定的程序正在处理代码中固定的字符串,例如

char str[100] = "With fixed string this code works"
// Output of the program is "fixed string this code works"

但是一旦我使用

输入 str
scanf("%s", &str);

似乎在内存分配中发现了错误,因为输入后给出了代码 returns 错误值。

完整代码如下

int main (void) {
    char str[100];
    char *p = (char *)malloc(sizeof(char) * str[100]);
    printf("Enter something: ");
    scanf("%s", &str);
    *p = str;
    p = strchr(str, ' ');
    puts(p + 1);

    // Check for the first space in given input string if found then 
    while (*p++)
        if (*p == ' ' && *++p)
            printf("%s", *p);

    printf ("\n\n");

    return 0;
}

不确定在使用 scanf 函数输入字符串时进行动态内存分配是否需要任何其他分配过程

您的 malloc 有一个错误:

char *p = (char *)malloc(sizeof(char)*str[100]);

我们先简单一点。


不要投malloc(参见:Do I cast the result of malloc?):

char *p = malloc(sizeof(char)*str[100]);

sizeof(char) 是(根据定义)在 all 架构上 always 1,无论它占用多少位,所以我们可以消除它:

char *p = malloc(str[100]);

现在我们有:

char str[100];
char *p = malloc(str[100]);

您有未定义的行为str 没有值(即单元化)并且您传递的元素是 数组末尾 之后的元素,因此您有未定义的行为。

因此,传递给 malloc 的长度参数是随机的。

Scanf %s 只读取字符串中的第一个空格然后停止,这可能是导致您出现问题的原因。无论如何我都会避免使用 scanf,它很危险,如果您不熟悉它可能会导致问题。您可以尝试 fgets 改为从 stdin 读取。看看这是否符合您的要求:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAX_LENGTH 100

int main (void) 
{
    char *str = (char *) malloc (sizeof(char) * MAX_LENGTH + 1);
    bzero(str, MAX_LENGTH + 1);

    printf("Enter something: ");
    fgets(str, MAX_LENGTH, stdin);

    // Remove the newline
    if ((strlen(str) > 0) && (str[strlen (str) - 1] == '\n'))
    {
        str[strlen (str) - 1] = '[=10=]';
    }

    char *p = strchr(str, ' ');

    if (p != NULL)
    {
        // Pointing to the space, which we will skip
        p++;
        printf ("%s\n\n", p);
    }
    return 0;
}

你有四个问题:


首先:和scanf,应该是这样的:

scanf("%s",str);

因为str是一个地址。还要确保 scanf 将扫描 stdin 中的字符串,直到它找到 space 或新行以及您不想要的内容。所以你最好使用 fgets(str, 100, stdin);.


其二:加上malloc,应该是这样的:

malloc(sizeof(char)*100)

因为str[100]没有具体的值。


第三:你不应该改变使用malloc

分配的内存地址

malloc 函数在堆中分配内存,return 分配内存的地址,所以你不应该这样做 p = strchr(str, ' '); 因为 strchr 会 return 第一次出现 space 的地址(由 malloc 编辑的地址 return 将丢失)。


第四:释放使用malloc

分配的内存

您应该释放使用 malloc 分配的内存,使用 free 函数获取分配的内存地址。

你的代码应该是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main (void) {
    char str[100];
    char *p = malloc(sizeof(char)*100); //Do NOT cast the return of malloc
    printf("Enter something: ");
    fgets(str, 100, stdin); //Use fgets to include the spaces between words 
    strcpy(p, str);//use stcpy to Not change the address of memory allocated

    //p = strchr(str, ' '); -->This step will change the address
    //of memory allocated using malloc
    //puts (p + 1);
    /*Instead you can do this*/
    char *c = strchr(str, ' ');
    puts(c+1);

    // Check for the first space in given input string if found then 
    char *mem =p;
    while (*p++)
      if (*p == ' ' && *++p)
        printf ("%s", p);

    printf ("\n\n");
    free(mem);

    return 0;
}