Nano Hash - криптовалюты, майнинг, программирование

инициализация указателя char в C

Я не очень понимаю указатель символов и то, как они работают.

Программа собирается, но вылетает при запуске.

 char *ab = NULL;
 //ab = "abc123"; // works fine
 sprintf(ab, "abc%d", 123); // this line seems to crash the program

Я не понимаю, как это может быть неправильно, когда sprintf принимает (char * str) в качестве первого аргумента.

Кто-нибудь может объяснить мне это?

15.06.2012

Ответы:


1

Вы не выделили памяти для использования с ab.

Первое присваивание работает, потому что вы присваиваете ab строковую константу: "abc123". Память для константных строк предоставляется компилятором от вашего имени: вам не нужно выделять эту память.

Прежде чем вы сможете использовать ab, например. sprintf вам потребуется выделить память с помощью malloc и выделить это пространство для ab:

ab = malloc(sizeof(char) * (NUM_CHARS + 1));

Тогда ваш sprintf будет работать до тех пор, пока вы освободите достаточно места с помощью malloc. Примечание: + 1 предназначен для нулевого терминатора< /а>.

В качестве альтернативы вы можете выделить немного памяти для ab, объявив его как массив:

char ab[NUM_CHARS + 1];

Без какого-либо выделения памяти для ab вызов sprintf попытается записать в NULL, что является неопределенным поведением; это причина вашего сбоя.

15.06.2012
  • sizeof(char) гарантированно будет 1 (не путать с CHAR_BITS), поэтому в этом нет необходимости. Вы также должны упомянуть, что вам нужно выделить место для завершающего '\0'. 15.06.2012

  • 2

    Вам нужно выделить память для ваших данных. Действительно, sprintf занимает char*, но не выделяет вам память.

    Первая строка работает нормально, потому что компилятор автоматически выделяет данные для постоянных таблиц символов, определенных во время компиляции.

    15.06.2012

    3

    В отличие от Java или других языков более высокого уровня, многие строковые функции библиотеки C не просто устанавливают ссылку на строку, вместо этого они работают с блоком предварительно выделенной памяти, называемым массивом символов.

    Ваша первая строка говорит, что ab указывает на несуществующую ячейку памяти.

    Вам повезет больше, если вместо char *ab = NULL; вы сделаете либо:

    char ab[12];
    

    or:

    char *ab = (char*)malloc(12);
    
    15.06.2012

    4

    Ты можешь это сделать

    char ab[10];  //allocate memory
    sprintf(ab, "abc%d", 123);
    
    15.06.2012

    5

    «ab» имеет значение null, и sprintf пытается в него записать, вы должны сначала выделить его.

    char ab[20];
    
    sprintf(ab, "abc%d", 123); //
    

    or

    char * ab = malloc(20); // new, whatever
    
    sprintf(ab, "abc%d", 123); //
    
    15.06.2012
  • new, whatever бесполезен, так как это C, а не C++ 15.06.2012

  • 6

    Здесь нужно подумать о нескольких вещах. Ваш исходный пример ниже:

    char *ab = NULL;
     //ab = "abc123"; // works fine
     sprintf(ab, "abc%d", 123); // this line seems to crash the program
    

    char *ab = NULL; является указателем на символ и инициализируется значением NULL;

    Я не думаю, что ab = "abc123"; работал нормально, если только он не выглядел как char *ab = "abc123";. Это потому, что вы инициализировали char *ab строкой, доступной только для чтения. Инициализация, вероятно, произошла во время компиляции.

    Ваша строка sprintf(ab, "abc%d", 123); не удалась, потому что вы не инициализировали память для указателя char *ab заранее. Другими словами, вы не сделали что-то вроде:

    ab = malloc((sizeof(char) * 3) + 1); /* + 1 allows for null string terminator. */
    

    Вы можете решить свою проблему одним из двух способов. Либо выделите динамическую память, как показано выше, либо вы можете сделать строку массивом фиксированной длины, например char ab[25] = {0};. Обычно я создаю массив длиной, например, 1024, 256 или некоторым числом, которое обычно покрывает большинство моих случаев длины строки. Затем я использую указатели на символы для функций, которые работают с массивом.

    15.06.2012
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..