【问题标题】:What is the error in following C code? [closed]以下C代码有什么错误? [关闭]
【发布时间】:2013-10-18 14:22:28
【问题描述】:

这个问题是在我的 Tally 面试问题中提出的 请帮助我并告诉我下面给出的 C 代码中的错误是什么。 我将不胜感激。

int main()
{
    char *p="Tally";
    strcpy(p,"piyush");
    printf("%s",p);
}

【问题讨论】:

  • 另外,与其大量反对和不解释,不如尝试一次将他指向正确的方向。 p 不是只读的。它只是不指向可修改的内存位置。为此,您必须将其设置为可修改的位置,例如p = new char[100] 或者,与C 呆在一起,p = malloc(100)。不过不要忘记错误检查。
  • @AlterMann 请你详细解释一下。我是编程新手
  • 很有可能,它不会打印任何东西(也许 SIGSEGV 除外)。
  • @arne p = malloc(100); 是给初学者的一段非常糟糕的代码。这在任何地方都没有意义。正确的做法是写char *p = malloc(sizeof(*p) * strlen("Tally")); strcpy(p, "Tally");。或者,简而言之char *p = strdup("Tally");

标签: c string


【解决方案1】:

这段代码中有几个“错误”(“错误”应该是什么意思)。

主要问题是代码调用了未声明的函数strcpyprintf。形式上,这是现代 C 中的编译错误。对于 printf,这是 C99 之前的 C 版本中未定义的行为。

如果我们解决了这个问题,那么strcpy 调用将尝试修改字符串文字。字符串文字不可修改。这种修改尝试将导致未定义的行为。

由于上面的 UB,无法说出传递给 printf 的内容,但看起来 printf 调用是为了执行输出到文本流而不用换行符完成最后一行。是否需要这样的换行符由实现定义。

最后,虽然它不是一个“错误”,但可以说const char * 指针通常应该用于指向字符串文字。

【讨论】:

  • +1,但我没有得到换行符点..​​....因为什么时候必须用换行符终止输出?如果是关于行缓冲,则保证在正常程序终止时关闭流(fclose 意味着刷新),所以这应该不是问题......
  • @Matteo Italia:好吧,标准中的文本流规范明确指出“最后一行是否需要终止换行符是实现定义的”。它使用了“要求”一词,但没有详细说明如果违反此要求会发生什么。我相信这应该意味着更多的只是一些后期的流冲洗。我猜这意味着在某些平台上,文本流 shall 在每行末尾都有换行符被认为是有效的。
  • 谢谢,我同意你的解释;我想这适用于一些过时的平台,其中文本文件存储为行列表,并且需要换行符以允许 CRT 将流拆分为行。 (供将来参考,该引文位于 §7.19.2, ¶2)。
【解决方案2】:

p 是指向字符串文字 "Tally" 的指针。您不能覆盖文字。

【讨论】:

    【解决方案3】:

    在第 3 行中,您存储了一个指向字符串文字的指针,然后您尝试用 strcpy 覆盖其内容;问题是,字符串文字是只读的(如果您尝试在其上写入,则为 UB,而在现代平台上通常会导致崩溃)。

    如果你想要一个可写的字符串,你必须分配一个本地缓冲区(足够宽以容纳你想要存储的任何数据)。

    尽管如此,这些是 C 中字符串处理的基础,我强烈建议您在继续之前在您的 C 书上修改这些参数。

    【讨论】:

      【解决方案4】:

      p 是一个指向五个字符串文字的指针。 piyush 有六个字符长。这将溢出分配给*p 的空间,即使没有,*p 由于声明的方式也无法修改。

      【讨论】:

      • p 被声明为 char * 本身并不禁止写入。它只是不指向可写位置。
      • 正确——p指向的数据不能被修改,因为它是一个字面量,所以我说*p不能被修改。 p 本身可以修改,他可以修改 p = "piyush" 甚至 p = malloc(7*sizeof(char)); strcpy(p, "piyush"),但我认为这不是他想要的。
      • 天哪。我在你最后一句话中过度阅读了p 上的*。不过,真正的问题是什么还不是很清楚。
      【解决方案5】:

      “Tally”在可执行文件的只读部分。你正试图改变它,它犹豫不决,因此失败了。有什么问题

      【讨论】:

        【解决方案6】:

        这一行是错误的

        char *p="Tally";
        

        指针没有必须写入的地址 例如,您可以这样做

        char t;
        char *p;
        p = &t;
        *p='a';
        

        o 和 char 你不能放一个字符串

        编辑 一个不错的链接 http://www.physics.drexel.edu/courses/Comp_Phys/General/C_basics/#pointers

        【讨论】:

        • char *p="Tally"; 行没有任何问题(除了const char *p="Tally"; 会更好)。
        • 罗伯特不要迷惑我
        • 通常你确实可以这样做,但在这个例子中你当然不能指任何东西
        • @RobertStevens:“什么都没有”是什么意思? p 被设置为指向字符串字面量,它不是nothing;只是尝试写入该位置会调用未定义的行为。
        【解决方案7】:

        回答你的面试问题 - 以下是这段代码的错误:

        1. No libraries included, hence printf and strcpy are undeclared functions
        
        2. int main() has no return in the code. return 0; is required // gcc will throw a warning when -Wall flag is set
        
        3. p is a string literal. Which can't be overwritten.
        

        编辑:

        对于那些说不需要 return 的人:这是使用 gcc 编译并设置 -Wall 标志时的结果:

        Notra:Desktop Sukhvir$ gcc -Werror -Wall -g -o try try.c
        cc1: warnings being treated as errors
        try.c: In function ‘main’:
        try.c:19: warning: control reaches end of non-void function
        

        如果 -Wall 未设置,授权编译器将忽略这一点,但包含它仍然是一个好习惯。 @AndreT gcc 发出警告的事实暗示它应该在那里。没有它,当然代码仍然可以编译.. 但这并不是一个好习惯

        编辑 2:

        当 gcc 被强制使用 C99 标准时,它会在没有警告的情况下编译。所以请忽略我帖子的第 2 点。

        【讨论】:

        • returnmain 中不是必需的。 C99 及更高版本将自动从 main 返回零。
        • @AndreyT 代码无法编译是 -Wall 标志在 gcc 中设置。包括返回值也是一种很好的做法
        • main中不需要return。
        • @sukhvir:我不确定您所说的“不会编译”是什么意思。编译此代码需要兼容的 C99(及更高版本)C 编译器。如果您的编译器拒绝这样做,则编译器或设置一定有问题。您使用的是什么版本的 GCC?您是否有机会在 C89/90 模式下编译?
        • GCC 仅在旧 C89/90 模式下使用时才会在 -Wall 模式下发出此警告。因此,如果您想针对该语言的旧版本进行回答,则必须特别注意它。在当前的 C 中,不存在此类问题,并且 GCC 不会生成警告。首先,如果要使用 GCC 编译 C 代码,需要 -std=c99 或更高的设置。其次,如果要通过GCC wanings来判断代码的有效性,你必须付出巨大的努力来正确配置GCC。在默认模式下,GCC 是一个充满荒谬反馈的幽默动物园。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多