C:使用指针作为字符串:不可预知的行为

标签 c string memory pointers getchar

我正在编写一个 C 程序来查找用户输入中最长的一行,并打印该行的长度和该行本身。它成功地计算了字符数,但无法预料地无法存储行本身。也许我误解了 C 的内存管理,有人可以纠正我。

编辑:后续问题:我现在明白 dummy 字符后面的 block 是未分配的,因此打开了计算机可以对它们执行任何操作的范围,但是为什么某些字符的存储是否仍然有效?在我提到的第二个例子中,程序将字符存储在“未分配” block 中,即使它“不应该”。为什么?

变量:

  • getchar() 存储在 c 每次我 getchar()
  • i 是我getchar()来自
  • 的当前行的长度(到目前为止)
  • longest_i 是目前最长的行的长度
  • twostr 指向两个字符串中第一个的开头:第一个为当前行,第二个为迄今为止最长的行。当发现一行最长时,将其复制到第二个字符串中。如果 future 的一行更长,它会覆盖第二个字符串的某些部分,但这没关系,因为我不会再使用它了——第二个字符串现在将从更靠右的位置开始。
  • dummytwostr 一个指向的地方

这是我可视化程序变量使用的内存的方式:

 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|\n| 7|11|15|c |u |r |r |e |n |t |\0|e |s |t |\0|p |r |e |v |l |o |n |g |e |s |t |\0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

真实陈述:

&c == 11
&i == 12
&longest_i == 13
&twostr = 14
&dummy = 15

程序:

#include <stdio.h>

int main()
{
    char c = '\0';
    int i, longest_i;
    char *twostr;
    longest_i = i = 0;
    char dummy = '\0';
    twostr = &dummy;

    while ((c=getchar()) != EOF)
    {
        if (c != '\n')
        {
            *(twostr+i) = c;
            i++;
        }
        else
        {
            *(twostr+i) = '\0';
            if (i > longest_i)
            {
                longest_i = i;
                for (i=0; (c=*(twostr+i)) != '\0'; ++i)
                    *(twostr+longest_i+1+i) = c;
            }
            i = 0;
        }
    }

    printf("length is %d\n", longest_i);
    for (i=0; (c=*(twostr+longest_i+1+i)) != '\0'; ++i)
        putchar(c);

    return 0;
}

*(twostr+longest_i+1))'\0'不可预测。示例:

输入:

longer line
line

输出:

length is 11
@

输入:

this is a line
this is a longer line
shorter line

输出:

length is 21
this is a longer lineÔÿ"

最佳答案

您实际上并没有分配任何内存来写入!

char dummy = '\0'; // creates a char variable and puts \0 into it
twostr = &dummy; // sets twostr to point to the address of dummy

在此之后,您只需写入由 dummy 预留的 char 之后的内存,并覆盖 who-knows-what。

在这种情况下,最简单的解决方法是使 dummy 成为一个指向 char 的指针,然后 malloc 一个缓冲区以用于您的字符串(使其比您期望的最长字符串长!)

例如,下面的 buffer 将指向 256 字节(在大多数系统上)的内存,允许字符串长达 255 个字符(因为您有空终止符 (\0) 来存储最后)。

char * buffer = (char *)malloc(sizeof(char) * 256);

编辑:这将从堆中分配内存,稍后您应该在完成后通过调用 free(buffer); 释放它。另一种方法是按照 Anders K 的解决方案用尽堆栈上的空间。

关于C:使用指针作为字符串:不可预知的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8441766/

相关文章:

c - 将 atexit 注册到嵌套函数会在 gcc 下返回段错误

不能在 C 中将 sscanf() 用于字符数组

python3.4如何删除模式字符串匹配后的一段文本

使用 Node.js 服务器调试内存泄漏

C 指针引用

c - 在 C 中实现最小堆

c - 为什么这个数学不适用于宏?

c# - 如何获取所有字符串格式参数

linux - memcachedslab和linux内核slab之间有什么关系

c - C 预处理器宏是否可以包含预处理器指令?