【问题标题】:C: Variable turns to 0 simply calling getline inside for loopC:变量变为0,只需在for循环中调用getline
【发布时间】:2015-07-16 10:56:35
【问题描述】:

在下面的代码(我的源代码的简化版本)中,变量lv 在声明时被初始化为1,当getline 在for 循环内被调用时,它神秘地变成了0。如果您输入除"cl" 以外的任何内容,您可能会从printf 或通过gdb 注意到它。变量在getline 调用后立即更改值。 最奇怪的是,当提示输入"cl"时,你可能通过gdb看到lv的值在getline之后变成0,然后在@987654333中正确设置为3 @ 语句,然后为后续循环保留,无论您输入什么。

此外,如果您将声明更改为 static int lv = 1;,则会发生预期的行为(lv 保持为 1,直到“手动”更改)。

谁能告诉我到底发生了什么?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( void ) {
  char* line=NULL;
  int len;
  int lv = 1;
  for(;;) { 
    printf("Level: %d\n", lv);

    getline(&line, (size_t*)&len, stdin);

    if (line[strlen(line) - 1] == '\n') {
      line[strlen(line) - 1] = '\0';
    }
    if (strcmp(line, "cl")==0) {
      lv = 3;
    } else if (strcmp(line, "hi")==0) {
      printf("Hello World!\n");
    } else if (strcmp(line, "quit")==0) {
      break;
    }
  }
  return 0; 
}

【问题讨论】:

  • 这是什么平台?
  • 另一个很好的例子,说明为什么不能盲目地“抛弃”编译器警告/错误。
  • size_t 是 typedefed 为 long 并且是保证保存任何数组索引的类型。我怀疑这是否真的能直接揭示出来。将len 声明为size_t 或long,它应该可以工作。
  • 正如其他人所说:size_t 是size_t。它不是int。它不是long。 是 size_t.
  • @alk 实际上我没有得到你的第一条评论,我的错:)。无论如何,这部分代码是从我大学操作系统教授的幻灯片中逐字提取的,所以这里真正的教训是不要相信演员,还有你的教授;)

标签: c variables for-loop static getline


【解决方案1】:

编译器会列出的一个问题是 getline()(在 linux 上)在 stdio.h 中没有原型,除非这样写:

   #define _GNU_SOURCE
   #include <stdio.h>
   #include <stdlib.h>

编译器还针对未使用的参数“argc”和“argv”提出了另外两个警告,建议将主函数声明更改为:

int main( void )

【讨论】:

  • 我的编译器(也是 linux)找到 getline 没有任何问题。 main 的参数是一个残留物:我切断了使用 argc 和 argv 的代码部分,但忘记在 main() 中删除它们,我正在编辑问题以保持一致性。
【解决方案2】:

一个合乎逻辑的解释是在您的平台上size_t 大于int。

如果是这种情况,您的代码有 UB,当 getline 更新 len 时,lv 变量会被覆盖。

只需将len 声明为size_t。

【讨论】:

  • 我认为你做对了。那么是不是选择了定义lvstatic另一个内存区域,所以不会发生覆盖?
猜你喜欢
  • 2021-06-13
  • 1970-01-01
  • 2021-01-20
  • 2018-06-30
  • 1970-01-01
  • 2015-03-25
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多