【问题标题】:Cannot Figure out Why "sizeof(msg) = 0" [closed]无法弄清楚为什么“sizeof(msg)= 0”[关闭]
【发布时间】:2020-11-23 20:52:19
【问题描述】:

我需要找到输入的消息的长度。我已将 msg 中的所有字符放入数组 msg[],但是当我检查此数组的大小时,结果为零。 感谢您的帮助。

#include <stdio.h>
#define SIZE ((int) (sizeof(msg)/sizeof(msg[0])))

int main(void){
    int i = 0,j = 0;
    char msg[i];
    char ch = ' ';
    printf("Please enter a msg you want traslated: ");
    while(ch != '\n'){
        scanf("%c",&ch);
        if(ch == '\n'){
            break;
        }
        i++;
        msg[j] = ch;
        j++;
    }
    printf("%d\n",SIZE);
    return 0;
}

【问题讨论】:

  • msg[i] 和 i=0 ?
  • int i = 0; char msg[i]; 尝试形成大小为 0 的可变长度数组是无效的 - 未定义的行为。一旦定义了一个数组,它的大小就不能改变。
  • 将 char msg[i] 更改为 char msg[50] 看看会发生什么。并不是说这是做任何事情的正确方法,但也许你会明白发生了什么。
  • 大小和长度是 C 中的两个不同概念。大小通常是分配的数据结构的长度(在分配时固定)。长度是分配的数据结构中实际元素的数量(例如,字符串中的字符数,或数组中的整数数),它是可变的。

标签: c scope declaration variable-length-array


【解决方案1】:

因为你有sizeof(char[0])。

您将可变长度数组msg 声明为char msg[0],然后写入未分配的内存位置(不会更改 sizeof 的值,根据定义,它是 to compute the number of elements in an array - 引用自 6.5 .3.4p6)。编写 msg[somethinh] = something 它是未定义的,您可能会在 sizeof 运算符被评估之前崩溃。

但是,通常,sizeof 会告诉您数组的大小,在您的情况下为 0,因为 i=0。

【讨论】:

    【解决方案2】:

    这就是问题所在。

    您正在定义一个零元素的数组:

    int i = 0,j = 0;
    char msg[i];
    

    如果你检查sizeof(msg),你会得到零。

    如果您检查 sizeof(msg[0]),您将得到 1(在数组的元素 0 处,char 是 1 个字节)。

    所以你在程序结束时的数学是正确的:0 / 1 == 0

    您需要做的是为数组分配一些空间,这将为msg 提供一个大小。如果你这样做:

    char msg[50]
    

    那么 sizeof(msg) 将是 50。因为 char 是 1 个字节,而您想要其中的 50 个:50 * 1 == 50

    我明白你在这里的目的。您想计算用户输入了多少元素。不幸的是,您不能使用此方法。无论循环进行多少次迭代,msg 数组始终为 50 字节。

    但是,您已经走在正确的道路上。每次有人添加某些内容时,您都会增加 i 和 j。所以在程序结束时你可以这样做:

    printf("User entered %d records\n", i);
    

    【讨论】:

      【解决方案3】:

      你困惑的原因是你没有正确理解变长数组。

      首先请注意,您不能声明大小等于0 的可变长度数组。所以无论如何这个数组声明

      int i = 0,j = 0;
      char msg[i];
      

      不正确。

      要更改数组msg 的大小,仅更改数组声明中使用的变量i 的值是不够的。要求程序的执行控制每次都要经过数组声明,得到一个新的值i。

      这是一个演示程序。

      #include <stdio.h>
      
      int main(void) 
      {
          int i = 1;
          
          L1:;
          char msg[i];
      
          printf( "The size of msg is %zu\n", sizeof( msg ) );
          
          if ( i++ < 10 ) goto L1;
      }
      

      程序输出是

      The size of msg is 1
      The size of msg is 2
      The size of msg is 3
      The size of msg is 4
      The size of msg is 5
      The size of msg is 6
      The size of msg is 7
      The size of msg is 8
      The size of msg is 9
      The size of msg is 10
      

      如您所见,在更改变量i 后,控制权转移到了标签L1。并且控件通过变量i的值来声明数组。

      但是数组中早期存储的值会丢失。

      根据 C 标准(6.2.4 对象的存储时长)

      7 对于这样一个具有可变长度数组类型的对象,它的 生命周期从对象的声明到执行 程序离开声明的范围。35) 如果范围是 以递归方式输入,每个对象都会创建一个新实例 时间。对象的初始值是不确定的。

      所以要么使用固定大小的字符数组,要么使用标准函数realloc在循环内动态重新分配数组。

      这是一个演示程序。

      #include <stdio.h>
      #include <stdlib.h>
      
      int main(void) 
      {
          char *msg = malloc( sizeof( char ) );
          size_t i = 0;
          
          printf( "Please enter a msg you want to translate: " );
      
          for ( char c; scanf( "%c", &c ) == 1 && c != '\n'; i++ )
          {
              char *tmp = realloc( msg, i + 1 );
              
              if ( tmp == NULL ) break;
              
              msg = tmp;
              msg[i] = c;
          }
          
          msg[i] = '\0';
          
          printf( "You entered %zu characters: %s\n", i, msg );
          
          free( msg );
          
          return 0;
      }
      

      它的输出可能看起来像

      Please enter a msg you want to translate: Humza Ahmed
      You entered 11 characters: Humza Ahmed
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-02-08
        • 1970-01-01
        • 2020-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-22
        相关资源
        最近更新 更多