【问题标题】:Input with char pointer vs. char array使用 char 指针与 char 数组输入
【发布时间】:2010-03-08 14:19:51
【问题描述】:

考虑代码

#include<stdio.h>
int main(void)
{
   char* a;
   scanf("%s",a);//&a and &a[0] give same results-crashes 
   printf("%s",a);
   return 0;
}

为什么这段代码会导致崩溃?而这段使用字符数组的代码可以正常工作?

#include<stdio.h>
int main(void)
{
   char a[100];
   scanf("%s",&a[0]);//works fine
   printf("%s",a);
   return 0;
}

区别在于字符数组和指针吗?但我知道指针只指向第一个元素 &a[0] 应该可以正常工作,但上面的代码对于所有三个 a、&a 和 &a[0] 都崩溃了? 我要收集的主要内容是,如果我坚持只使用 scanf,我该如何输入字符指针? 如果我不清楚,我很抱歉。 在此先感谢:)

【问题讨论】:

  • 请了解如何标记代码以使其可读。
  • 对不起,我很新。我再次道歉
  • 所以这不是作业,否则我会标记它
  • 我建议更改两个示例中的数组/字符串名称,以便在回答时更容易区分它们。
  • 是时候指出“数组并不总是等价于指针!”。

标签: c input


【解决方案1】:

因为char* a; 在堆栈上为字符指针分配空间,而char a[100]; 为 100 个字符分配空间。

在前一种情况下,您需要为指针指向的分配一些实际内存。导致您崩溃的原因是a 被设置为某个任意值(您没有对其进行初始化),并且当您scanf 时,这就是写入数据的位置。如果你只使用a,我们就称它为第一类崩溃。

如果您使用&amp;a,它会将您的输入写入指针本身,这将为您留下一个指向谁知道哪里的指针,从而导致第二类崩溃。这是假设您输入的字符数不会超过指针溢出 - 这会破坏调用堆栈,导致 另一个 崩溃情况(类型三)。

作为忠告,请不要使用没有边界检查的输入函数,除非您完全可以控制向它们呈现的数据。即使使用char[100],也有人可能会通过输入超出缓冲区容量的字符而导致代码中的堆栈溢出。

我发现最好的办法是将fgets可以限制读取的字符)与sscanf结合使用(尽管如果你得到的只是一个字符串,@ 987654330@ 并不是真正需要的)。

【讨论】:

    【解决方案2】:

    a 不指向任何东西。或者实际上,它没有初始化,所以它指向某个地方,只是某个地方无效。

    您可以像已经尝试过的那样在堆栈上提供存储:

    #include <stdio.h>
    int main()
    {
      char x[100];
      char *a = x; // a points to the storage provided by x on the stack
      scanf("%s",a); // should work fine
      printf("%s",a);
      return 0;
    }
    

    请注意,printf("%s",x); 产生完全相同的结果,a 指向 x,所以这就是您的字符串将“生存”的地方。

    或者你可以让内存管理使用 malloc 来处理它

    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
      char *a = malloc (100*sizeof(char)) // a points to the storage provided by malloc
      if (a != null)
        {
          perror ("malloc"); // unable to allocate memory.
          return 1;
        }
      scanf("%s",a); // should work fine
      printf("%s",a);
      free (a); // just remember to free the memory when you're done with it.
      return 0;
    }
    

    HTH。

    编辑
    此外,在 cmets 开始之前......这是非常不安全的代码,但我想你只是想把你的头绕在指针上,所以我只是想给你一个正确的方向。 (如果不是,您需要考虑读取有限数量的数据,确保它适合您的缓冲区,如果它来自文件以外的其他来源,您需要确保您获得了所有数据,依此类推,依此类推)。

    【讨论】:

      【解决方案3】:

      在使用amalloc() 之前,您必须为其分配内存。

      【讨论】:

      • @qrdl 我想知道参考内存崩溃的原因
      • 如果不分配内存,您的a 会指向内存中的某个随机位置,该位置很可能不属于您的进程,因此尝试访问此内存会导致分段错误。
      • int *a; 只是声明一个指针。它实际上并没有给它任何指向的记忆。 scanf 假设你给它的指针指向一个足够大的内存空间来满足它的需要。由于您从未在任何地方指向 a,因此程序崩溃了。
      【解决方案4】:

      scanf 需要一个地方来放置它读取的字符。您可以将一个指向字符数组的指针(在第二个示例中所做的)传递给它,或者将一个指向以另一种方式获得的内存的指针(比如 malloc())传递给它。在您的第一个示例中,您向它传递了一个未初始化的指针,因此您正在观察到的问题。

      【讨论】:

      • @aprogrammer 你的意思是说我需要初始化指针,比如 char* a=""
      • 您需要使用指向您可以写入的内存的指针值来初始化指针变量。你在这里建议的是初始化它——这比你做的要好——但是你不能写入那个内存(即使你可以在那里写它也可能太小了)。
      【解决方案5】:

      在第一个例子中,a 是一个“悬空指针”——它是一个包含某个随机内存位置地址的指针。在大多数情况下,访问此地址会导致崩溃。底线:您需要为 a 分配内存。

      【讨论】:

        【解决方案6】:

        在您的第一个代码中,a 是一个未初始化的指向 char 的指针。 您正在尝试写入未分配的内存或保留的内存。

        你需要为malloc()的输入字符串分配内存。


        int main(void) {
          char* s;
          /* ... */
          s = malloc(100 * sizeof(*s));
          if (s == NULL) {
            return 1;
          /* ... */
        }
        

        【讨论】:

          猜你喜欢
          • 2018-04-05
          • 2021-01-26
          • 1970-01-01
          • 2015-10-26
          • 1970-01-01
          • 1970-01-01
          • 2012-03-19
          • 1970-01-01
          • 2012-10-29
          相关资源
          最近更新 更多