1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Измерение размера массива в функции

Тема в разделе "Оффтопик", создана пользователем gelion, 5 июн 2019.

  1. Автор темы
    gelion

    gelion Активный участник Пользователь

    Баллы:
    78
    Так как это вопрос о языке Си,а не java, то выношу его в раздел оффтопика

    Допустим мы объявили массив символов:
    char str[] = "Go to minecraft";

    Хочу узнать его длину, используя sizeof. Таким вот образом:
    printf("len = %d\n", sizeof(str)/sizeof(char));

    Но если, мы передаем этот массив в функцию
    char* CopyStr(char* str){
    printf("sizeof(str) = %d; sizeof(char) = %d", sizeof(str),sizeof(char));
    return str;
    }

    То sizeof(str) = 4

    Вроде бы все правильно) Ведь str это указатель на первый элемент в массиве. Но в главной программе sizeof как-то распознает, что это массив.

    Так вот вопрос, как sizeof узнает, что это массив? Из контекста?
    И как в функции узнать длину массива? Используя стандартные средства.
     
  2. Автор темы
    gelion

    gelion Активный участник Пользователь

    Баллы:
    78
    Похоже действительно из контекста, так как если в самом начале создать указатель на первый элемент в массиве, то применяя к нему sizeof получаем размер указателя, а не массива
     
  3. IlyaHaker

    IlyaHaker Активный участник Пользователь

    Баллы:
    76
    если посмотреть, как расположены элементы массива в памяти, сразу будет понятно, почему так
     
  4. Автор темы
    gelion

    gelion Активный участник Пользователь

    Баллы:
    78
    Если не в состоянии объяснить, мог бы и молчать. Без обид, но "я типо знаю, но не скажу. Вот те тонкий намек", немного бесит.

    Все же это вполне конкретный вопрос (если нет, то всегда можно прямо на это ткнуть, тут я полностью согласен)
     
  5. HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    sizeof рассчитывается на этапе компиляции. В контексте, где объявлен char [], компилятор видит массив с известной ему длиной, т.е., формально, ты делаешь sizeof(char[N]), а не sizeof(char*), а в контексте с указателем компилятор видит только абстрактный, ни к чему не привязанный адрес и ожидаемо выдаёт размер указателя.

    В функции узнать размер такого массива нельзя, поэтому или передавай размер явно, или оборачивай массив в структуру или класс-контейнер (например, для строк используй std::string, для массивов бинарных данных - std::vector):
    Код:
    struct data {
        char* buf;
        unsigned size;
    };
    
    void func(data* d)
    {
        printf("%u: %s\r\n", d->size, d->buf);
    }
    
    int main()
    {
        char text[] = "text";
        data d;
        d.buf = text;
        d.size = sizeof(text);
        func(&d);
    }
    
    или

    Код:
    #include <string>
    
    void func(const std::string& str)
    {
        printf("%i %s\r\n", (int)str.length(), str.c_str());
    }
    
    int main()
    {
        const char* txt = "text";
        void func(txt);
    }
    
     
    Последнее редактирование: 9 июн 2019
  6. HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Если же тебе надо получить длину строковых данных, используй strlen для ANSI-строк или wcslen для Wide-строк.

    За конец строки принимается нуль-терминатор - байт 0х00 в конце строки. strlen и wcslen идут по строке и ищут этот байт (wcslen ищет не байт, а два байта, т.к. wchar_t - это 16-битное слово, 2 байта в UTF-16). Если нашли - вот тебе и длина. Если не нашли - будем искать до тех пор, пока или не найдём, или не упрёмся в границу выделенной памяти (и словим эксепшн).
     
  7. HoShiMin

    HoShiMin Старожил Пользователь

    Баллы:
    173
    Посмотрел и, исходя из расположения в памяти, мне вот непонятно, почему так.
     
  8. IlyaHaker

    IlyaHaker Активный участник Пользователь

    Баллы:
    76
    а, да, ошибся((

    а вообще, sizeof() и не знает, что это массив, он знает только, сколько памяти выделено под переменную, указанную в качестве аргумента
     

Поделиться этой страницей