【问题标题】:Character arrays in CC中的字符数组
【发布时间】:2011-10-25 17:26:03
【问题描述】:

我是 c 的新手。只是对c中的字符数组(或字符串)有疑问:当我想在C中创建一个字符数组时,我必须同时给出大小吗?

因为我们可能不知道我们实际需要的尺寸。比如客户端-服务端程序,如果我们想声明一个字符数组让服务端程序接收来自客户端程序的消息,但是我们不知道消息的大小,我们可以这样:

char buffer[1000];
recv(fd,buffer, 1000, 0);

但是如果实际消息的长度只有 10 怎么办。这会导致大量内存浪费吗?

【问题讨论】:

  • 在 C 中搜索“动态内存分配”
  • 正如您所说,这将是“浪费”内存,因为您不能期望提前知道需要保留多少。因此,您将保留足够的资金,以应对大多数情况,同时仍然意识到您实际上可能需要更多。
  • 你不会在 C++ 中遇到这个问题,它有一个内置的字符串类型而不是使用字符数组。当然,你可能有一大堆不同的问题,但也许你应该看看。

标签: c arrays string character


【解决方案1】:

是的,你必须提前确定维度,即使你使用 malloc。

当您从套接字读取时,如示例中所示,您通常使用大小合理的缓冲区,并在您使用它时立即以其他结构调度数据。在任何情况下,1000 字节都不会浪费太多内存,并且肯定比从某个内存管理器一次询问一个字节要快:)

【讨论】:

    【解决方案2】:

    即使你使用 malloc 也必须先定义大小!因此,您改为提供能够接受消息的大量数字,例如:

    int buffer[2000];   
    

    如果是小消息或大消息,您可以重新分配它以释放未使用的位置或占用未使用的位置

    example:
    int main()
    {
     char *str;
    
      /* Initial memory allocation */
      str = (char *) malloc(15);
      strcpy(str, "tutorialspoint");
      printf("String = %s,  Address = %u\n", str, str);
    
      /* Reallocating memory */
      str = (char *) realloc(str, 25);
      strcat(str, ".com");
      printf("String = %s,  Address = %u\n", str, str);
    
      free(str);
    
      return(0);
     }
    

    注意:确保包含 stdlib.h 库

    【讨论】:

      【解决方案3】:

      如果您不知道先验大小,那么您别无选择,只能使用 malloc(或您选择的语言中的任何等效机制)动态创建它。

      size_t buffer_size = ...; /* read from a DEFINE or from a config file */
      char * buffer = malloc( sizeof( char ) * (buffer_size + 1) );
      

      创建大小为m 的缓冲区,但只接收大小为nn < m 的输入字符串不是浪费内存,而是工程上的妥协。

      如果您创建的缓冲区大小接近预期输入,则对于m >> n 的情况,您可能不得不多次重新填充缓冲区。通常,缓冲区上的迭代与 I/O 操作相关,因此现在您可能会节省一些字节(这在当今的硬件中实际上是什么),但代价是可能会增加另一端的问题。特别适用于客户端-服务器应用程序。如果我们谈论的是资源受限的嵌入式系统,那就另当别论了。

      您应该担心自己的算法是否正确可靠。然后,如果可以的话,您会担心在这里和那里削减几个字节。

      对我来说,我宁愿创建一个比平均输入大 2 到 10 倍的缓冲区(不是您的情况下的最小输入,而是平均值),假设我的输入在尺寸。否则,我会增加 20 倍或更多的大小(特别是如果内存很便宜并且这样做可以最大限度地减少对磁盘或 NIC 卡的影响。)

      在最基本的设置中,通常将缓冲区的大小作为从文件中读取的配置项(或作为参数传递),如果没有提供则默认为default compile time value。然后您可以根据观察到的输入大小调整缓冲区的大小。

      更复杂的算法(例如 TCP)在运行时调整其缓冲区的大小,以更好地适应大小可能/将随时间变化的输入。

      【讨论】:

        【解决方案4】:

        当您不知道输入数据的确切数量时,请执行以下操作:

        1. 创建一个小缓冲区
        2. 为“存储”分配一些内存(例如两倍的缓冲区大小)
        3. 用输入流(例如套接字、文件等)中的数据填充缓冲区
        4. 将数据从缓冲区复制到存储中

          4.1 如果存储空间不足,重新分配内存(例如,大小是此时的两倍)

        5. 除非出现“END OF STREAM”,否则执行第 3 步和第 4 步

          您的存储现在包含数据。

        【讨论】:

          【解决方案5】:

          您要问的是如何动态调整缓冲区大小。这是通过动态分配完成的,例如使用malloc()——一个内存分配器。但是,使用它会给您带来重要的责任:当您使用完缓冲区后,您必须自己将其返回给系统。如果使用 malloc() [或 calloc()],则返回 free()

          例如:

          char *buffer; // pointer to a buffer -- essentially an unsized array
          buffer = (char *)malloc(size);
          // use the buffer ...
          free(buffer); // return the buffer -- do NOT use it any more!
          

          剩下的唯一问题是如何确定您需要的尺寸。如果您正在接收提示大小的数据,则需要将通信分成两个 recv() 调用:首先获取所有数据包将具有的最小大小,然后分配完整缓冲区,然后是 recv'剩下的。

          【讨论】:

            【解决方案6】:

            是的,如果您在声明时没有初始化 char 数组,则必须给出大小。解决问题的更好方法是在运行时确定缓冲区的最佳大小并动态分配内存。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2013-08-16
              • 2014-10-23
              • 2017-08-31
              • 2011-01-22
              相关资源
              最近更新 更多