строка не заканчивается в ПУСТОМ УКАЗАТЕЛЕ, но все еще обычно ведет себя, почему?

typedef char byte;

Теперь можно заставить массив быть byte с. Для всех очевидно, что Вы имели в виду, и Вы не теряете функциональности.

я знаю, что это несколько глупо, но это заставляет Ваш код считать 100%, как Вы предназначили.

6
задан sharptooth 23 September 2009 в 11:08
поделиться

6 ответов

Что касается вашего редактирования, я думаю, что педантизм поможет прояснить некоторые проблемы.

В C нет такой вещи, как строка. Существует концепция "строки C", с которой работает стандартная библиотека C, которая определяется как не что иное, как последовательность символов с завершением NUL, поэтому на самом деле не существует такой вещи, как "строка, не завершающаяся нулевым символом. "в C. Итак, ваш вопрос лучше сформулировать как" Как я могу определить, является ли произвольный символьный буфер допустимой строкой C? " или «Как я могу определить, является ли найденная мной строка предполагаемой строкой»

Ответ на первый вопрос, к сожалению, состоит в том, чтобы просто линейно сканировать буфер, пока вы не встретите байт NUL, как вы это делаете. Это даст вам длину строки C.

На второй вопрос нет простого ответа. Из-за того, что C не имеет фактического строкового типа с метаданными длины (или способности переносить размер массивов между вызовами функций), нет реального способа определить, является ли длина строки, которую мы определили выше, длиной предполагаемая строка. Это может быть очевидно, если мы начнем видеть ошибки сегментации в программе или "мусор" в выводе, но в целом мы застряли, выполняя строковые операции, сканируя до первого байта NUL (обычно с верхней границей длины строки, чтобы избежать беспорядка ошибки переполнения буфера)

6
ответ дан 8 December 2019 в 04:30
поделиться

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

Скорее всего malloc () выделяет больше памяти и помещает так называемый защитные значения , которые содержат нулевые байты, или они помещают некоторые метаданные, которые будут использоваться free () позже, и эти метаданные содержат нулевой байт прямо в этой позиции.

В любом случае вы не следует полагаться на такое поведение. Вы должны запросить ( malloc () ) еще один байт для нулевого символа, чтобы местоположение нулевого символа также было легально выделено вам.

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

В идеале вам нужна какая-то функция, которая проверяет, выделен ли данный адрес для Вы и принадлежите к тому же распределению, что и другой заданный адрес (возможно, начало блока). Это будет медленным и не стоит того, и стандартного способа сделать это не существует.

Другими словами, если вы встретите строку, которая должна быть завершена нулем, но на самом деле это не так, вы сильно облажались - ваш программа будет работать с неопределенным поведением.

В идеале вам нужна какая-то функция, которая проверяла бы, выделен ли вам данный адрес и принадлежит тому же распределению, что и другой данный адрес (возможно, начало блока). Это будет медленным и не стоит того, и стандартного способа сделать это не существует.

Другими словами, если вы встретите строку, которая должна быть завершена нулем, но на самом деле это не так, вы сильно облажались - ваш программа будет работать с неопределенным поведением.

В идеале вам нужна какая-то функция, которая будет проверять, выделен ли вам данный адрес и принадлежит тому же распределению, что и другой заданный адрес (возможно, начало блока). Это будет медленным и не стоит того, и стандартного способа сделать это не существует.

Другими словами, если вы встретите строку, которая должна быть завершена нулем, но на самом деле это не так, вы сильно облажались - ваш программа будет работать с неопределенным поведением.

15
ответ дан 8 December 2019 в 04:30
поделиться

Sharptooth объяснил вероятную причину такого поведения, поэтому я не буду повторять это.

При распределении буферов я всегда выделяю избыточное количество байтов , например:

#define SIZE 10
char* buf = malloc(sizeof(char)*(SIZE+1));
/* error-check the malloc call here */
buf[SIZE] = '\0';
0
ответ дан 8 December 2019 в 04:30
поделиться

Почему это работает?

Выделенная вами память содержит '\ 0' байт в нужном месте. (Например, если вы используете Visual C ++ в режиме отладки, диспетчер кучи обнуляет выделенную память перед тем, как передать ее вашей программе. Но с таким же успехом это может быть чистая удача.)

Есть ли правильный способ проверьте, заканчивается ли строка на '\ 0' или нет?

Нет. Вам нужно, чтобы ваши строки либо оканчивались нулем (чего ожидают функции обработки строк в C std lib), либо вам нужно переносить их длину в дополнительной переменной. Если у вас нет ни одного из двух, у вас ошибка.

Теперь, как мы узнаем, что некоторая строка из некоторой функции, разработанной другим программистом, заканчивается в правильном месте на '\ 0' . Может быть нет, тогда он будет выходить за пределы фактического размера, пока мы не получим '\ 0' . Мы никогда не сможем узнать реальный размер строки.

Так как же нам справиться с такой ситуацией?

Вы не можете. Если другая функция так сильно облажалась, вы так сильно облажались.

4
ответ дан 8 December 2019 в 04:30
поделиться

Вам повезло, что у вас есть ноль за пределами выделенной области пространства.

Попробуйте этот код на всех других платформах, и вы увидите, что он может вести себя иначе.

0
ответ дан 8 December 2019 в 04:30
поделиться

Я думаю, что острозубый ответ правильный. Выделено больше места. Я модифицирую программу следующим образом:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10

int main()
{
    char *str ;
    int *p;
    int actual_length;
    str = malloc( sizeof( char ) * SIZE );
    if( str == NULL ) 
        exit( 1 );

    actual_length = (int)*(str - 4) - 1 - 4;
    printf("actual length of str is %d\n", actual_length);
    p = (int*) malloc(sizeof(int));
    if (p == NULL) exit(1);
    *p = -1;
    char* pc = (char*)(p - 1);
    pc [0] = 'z';
    pc [1] = 'z';
    pc [2] = 'z';
    pc [3] = 'z';

    memset( str, 0, sizeof( char ) * SIZE );

    memcpy( str, "abcdefghijklmnopqrstuvwxyz", sizeof( char ) * SIZE );

    int i;
    for (i = SIZE; i < actual_length; i++)
     str[i] = 'y';

    unsigned int index;
    for( index = 0; str[ index ] != '\0' ; index++ ) {
        printf( "str[ %u ] has got : %c \n ", index, str[ index ] );
    }

    return 0;
}

Результат:

actual length of str is 12
str[ 0 ] has got : a 
 str[ 1 ] has got : b 
 str[ 2 ] has got : c 
 str[ 3 ] has got : d 
 str[ 4 ] has got : e 
 str[ 5 ] has got : f 
 str[ 6 ] has got : g 
 str[ 7 ] has got : h 
 str[ 8 ] has got : i 
 str[ 9 ] has got : j 
 str[ 10 ] has got : y 
 str[ 11 ] has got : y 
 str[ 12 ] has got : z 
 str[ 13 ] has got : z 
 str[ 14 ] has got : z 
 str[ 15 ] has got : z 
 str[ 16 ] has got : \377 
 str[ 17 ] has got : \377 
 str[ 18 ] has got : \377 
 str[ 19 ] has got : \377 

Моя ОС - Debian Squeeze / sid.

0
ответ дан 8 December 2019 в 04:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: