代码之家  ›  专栏  ›  技术社区  ›  Patrick

fscanf的不同输入类型[关闭]

  •  -3
  • Patrick  · 技术社区  · 8 年前

    我对fscanf的理解:

    这就是说,有三种(看起来不同的)方式来传递“字符串”(字符数组)。

    一些假设:

    2.文件中有一行内容为“Something”

    char* temp = malloc(sizeof(char) * 1); // points to some small part in mem.
    int resp = fscanf(fp,"%s", temp); 
    printf("Trying to print: %s\n",temp); // prints "Something" (that's what's in the file)
    

    具有预定义长度的数组(与指针不同!)

    char temp[100]; // this buffer MUST be big enough, or we get segmentation fault
    int resp = fscanf(fp,"%s", temp); 
    printf("Trying to print: %s\n",temp); // prints "Something" (that's what's in the file)
    

    空指针

    char* temp; // null pointer
    int resp = fscanf(fp,"%s", temp); 
    printf("Trying to print: %s\n",temp); // Crashes, segmentation fault
    

    因此,出现了几个问题!

    1. malloc为1的指针如何包含更长的文本?
    2. 既然指针的内容似乎无关紧要,为什么空指针会崩溃?我预计分配的指针也会崩溃,因为它指向一小块内存。
    3. char temp[1];

    编辑:

    我很清楚,你需要传递一个足够大的缓冲区来包含来自线路的数据,我想知道为什么它仍然在工作,并且 在其他情况下。

    4 回复  |  直到 8 年前
        1
  •  2
  •   John Bollinger    8 年前

    我对fscanf的理解:

    格式,将其存储到字符串。

    不,这包含了一些严重而重要的误解。 fscanf()

    在您的特定用法中,

    int resp = fscanf(fp,"%s", temp);
    

    这就是说,有三种(看起来不同的)方式来传递“字符串”(字符数组)。

    字符串不是C中的实际数据类型。字符数组是,但这种数组不是C意义上的“字符串”,除非它们至少包含一个空字符。此外,在这种情况下,C字符串函数在大多数情况下仅对此类数组中直到并包括第一个空值的部分进行操作,因此这些部分最好被描述为“字符串”。

    只有 通过指针。即使在声明字符数组并通过应用索引运算符访问元素时, [] ,对于数组变量的名称,实际上仍在使用指针访问内容。

    指针只包含自身。它指向的空间包含任何其他内容,例如文本。如果只分配一个字节,则分配的空间只能包含一个字节。如果您试图在指针指向的位置写入更长的字符序列,从而超出了这一字节,那么您可以调用 未定义的行为 可以 接踵而至,没有限制。

    1. 既然指针内容似乎无关紧要,为什么空指针会崩溃,我预计分配的指针会崩溃为 嗯,因为它指向一小块内存。

    试图取消引用无效指针(包括但不限于空指针)也会产生未定义的行为。崩溃完全在可能的行为范围内。在这种情况下,C不能保证崩溃,但某些实现可以可靠地提供这一点。

    1. 为什么指针工作,而不是数组(char temp[1];)撞车?

    未定义 因此,假设该行为与超出已分配对象的边界的行为相同,甚至其中任何一种行为都是一致的,这是不合理的。

        2
  •  1
  •   alk    8 年前

    这就是说,有三种(看起来不同的)方式来传递“字符串”(字符数组)。

    scanf() &朋友只有一种方法:把足够有效内存的地址传给它。

    如果不这样做,代码将调用未定义的行为,这意味着任何事情都可能发生,从崩溃到看起来运行良好。

        3
  •  0
  •   Sergey Kalinichenko    8 年前

    从理论上讲,它不能不引起未定义的行为。然而,实际上,当您分配一个字节时,分配器会给您一小块其支持的最小大小的内存,这通常足以容纳8到10个字符,而不会导致崩溃。额外的内存用作防止崩溃的“填充”(但它仍然是未定义的行为)。

    另一方面,空指针即使对于空字符串也是不够的,因为您需要空终止符的空间。因此,它是一个有保证的UB,在大多数平台上表现为崩溃。

    char temp[1] )撞车?

    因为数组在分配后没有任何额外的“填充”内存。请注意,不能保证崩溃,因为数组后面可能有未使用的内存字节,您的字符串可能会损坏这些字节而不会产生任何后果。

        4
  •  0
  •   iBug    8 年前

    因为

    当您请求一小块内存时,它是从一块称为“堆”的内存中分配的。堆总是以块或页为单位进行分配和释放,这些块或页总是略大于几个字节,通常是几个KBs。

    所以当你分配内存时 new 理论上,这是一个UB和 应该 使程序崩溃

    创建空指针时,它指向0, 这是无法读取或写入的。因此可以保证程序会崩溃,通常是由于分段错误。

    malloc 没有任何额外空间