Не могу понять, почему «sizeof (msg) = 0» [закрыто]

Мне нужно найти длину введенного сообщения. Я поместил все символы сообщения в массив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;
}
# scope declaration variable-length-array
Источник
  • 8
    msg[i] и i=0 ?
  • 2
    int i = 0; char msg[i]; является недопустимой попыткой сформировать массив переменной длины размером 0 - неопределенное поведение. После определения массива его размер не может измениться.
  • 0
    замените char msg[i] на char msg[50] и посмотрите, что произойдет. Не то чтобы это правильный способ сделать что-либо из этого, но, возможно, вы тогда поймете, что происходит.
  • 1
    Размер и длина - это два разных понятия в C. Размер обычно - это длина выделенной структуры данных (она фиксируется во время выделения). Длина - это количество фактических элементов в выделенной структуре данных (например, количество символов в строке или количество целых чисел в массиве) и ее переменная.
Codelisting
за 0 против
Лучший ответ

Итак, вот в чем проблема.

Вы определяете массив с нулевыми элементами:

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 array всегда будет иметь размер 50 байтов, независимо от того, сколько итераций займет ваш цикл.

Но вы уже на правильном пути. Вы увеличиваетеi а такжеj каждый раз, когда кто-то что-то добавляет. Итак, в конце программы вы можете сделать:

printf("User entered %d records\n", i);
за 1 против

Причина вашего замешательства в том, что вы неправильно понимаете массивы переменной длины.

Для начала учтите, что вы не можете объявлять массив переменной длины с размером, равным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

Как видите, управление передается меткеL1 после изменения переменнойi . И управление проходит через объявление массива со значением переменнойi .

Но ранние сохраненные значения в массиве будут потеряны.

Согласно стандарту C (6.2.4 Срок хранения объектов)

7 For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.35) If the scope is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate.

Поэтому либо используйте массив символов фиксированного размера, либо динамически перераспределяйте массив внутри цикла с помощью стандартной функции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
за 0 против

Это потому, что у тебя естьsizeof(char[0]) .

Вы объявили массив переменной длиныmsg в качествеchar msg[0] и после этого вы пишете в нераспределенных ячейках памяти (не меняет значение sizeof, которое, по определению,to compute the number of elements in an array - цитата из 6.5.3.4п6). Написание msg [somethinh] = что-то неопределенное, и вы можете ожидать, что произойдет сбой до того, как будет оценен оператор sizeof.

Но, как правило, sizeof сообщит вам размер массива, который в вашем случае был 0, поскольку i = 0.

Codelisting
Популярные категории
На заметку программисту