C 无法理解为什么“sizeof(msg)=0”

C 无法理解为什么“sizeof(msg)=0”,c,scope,declaration,variable-length-array,C,Scope,Declaration,Variable Length Array,我需要找到输入的消息的长度。我已将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

我需要找到输入的消息的长度。我已将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;
}
这是因为您有sizeofchar[0]

您将可变长度数组msg声明为char msg[0],然后在未分配的memmory位置中写入,不会更改sizeof的值,根据定义,sizeof用于计算数组中的元素数-引用6.5.3.4p6。写入msg[somethinh]=它未定义的内容,您可能会在计算sizeof运算符之前崩溃

但是,作为一项规则,sizeof将告诉您数组的大小,在您的例子中,当i=0时,数组的大小为0。

所以问题就在这里

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

int i = 0,j = 0;
char msg[i];
如果您检查SizeofMg,您将得到零

如果检查SizeOfMg[0],您将在数组的元素0处得到1,char是1字节

因此,程序末尾的数学是正确的:0/1==0

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

char msg[50]
那么SizeofMg将是50。因为一个字符是一个字节,你需要50个:50*1==50

我知道你在这里干什么。您需要计算用户输入的元素数。不幸的是,您不能使用此方法。无论循环进行多少次迭代,msg数组始终为50字节

但是,你已经走上了正确的道路。每次有人添加内容时,您都会增加i和j。因此,在课程结束时,您可以:

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

造成混淆的原因是您没有正确理解可变长度数组

首先要考虑的是,不能声明大小等于0的可变长度数组。所以在任何情况下,这个数组声明

int i = 0,j = 0;
char msg[i];
这是不正确的

要更改数组msg的大小,仅更改我在数组声明中使用的变量的值是不够的。要求程序的执行控制每次都通过数组声明来获得新的值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;
}
#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;
}
如您所见,在更改变量i之后,控件被转移到标签L1。控件使用变量i的值进行数组的声明

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

根据C标准6.2.4物品的储存期限

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

因此,要么使用固定大小的字符数组,要么使用标准函数realloc在循环中动态重新分配数组

这是一个演示程序

#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;
}
#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;
}

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