2013-05-07 3 views
9

Это хорошо определен C++ передать зЬй :: вектор к API, C, которые ожидают выходной массив как это потому, что станд :: вектор смежный:Можно ли передать std :: string в API-интерфейсы C?

std::vector<char> myArray(arraySize); 
cStyleAPI(&myArray[0], arraySize); 

Безопасно передать зЬй :: строку в том же API для API? Есть ли какая-либо гарантия в стандартном C++ 03, что std :: string является непрерывной и работает так же, как и std :: vector в этой ситуации?

ответ

9

Если для функции C API требуется доступ только для чтения к содержимому std::string, используйте функцию члена std::string::c_str() для передачи строки. Это гарантируется строка с нулевым завершением.

Если вы собираетесь использовать std::string как из параметра, C++ 03 не гарантирует, что хранимая строка является непрерывной в памяти, но C++ 11 делает. С последним это нормально изменить строку через operator[], пока вы don't modify the terminating NULL character.

+0

c_str() возвращает const char *, и мне нужно иметь возможность получать вывод в строку. Можно ли это сделать без использования const_cast и c_str()? – masrtis

+0

@masrtis Нет, это все еще не так, но тогда почему бы вам не использовать 'char buf [BUFSIZE]'? – 2013-05-07 17:49:02

+0

@masrtis Ну, практически на самых разумных условиях? Да! Но теоретически гарантируется стандартом? Точно нет! –

0

Нет, это не так, но в целом потому, что строки C считаются нулевыми, что ваш указатель на char не является. (Если вы используете string, вы можете использовать вместо string::c_str(), это 0 завершающим.)

В любом случае, C++ 11 требует элементов vector быть смежными в памяти.

1

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

0
cStyleAPI(&myArray[0], arraySize); 

Если cStyleAPI получает символ * для ввода, то есть то, что std::string::c_str() для.

Если он получает предопределенный символ * для вывода, то нет. В этом случае вы должны использовать std::vector<char> или std::array<char>.

5

Итак, я знаю, что это было отвечено уже, но я видел ваш комментарий в ответ преторианской в:

Это ошибка драйвера OpenGL, что приводит возвращаемое значение для строки максимальная длина была нарушена. См. https://forums.geforce.com/default/topic/531732/glgetactiveattrib-invalid/. glGetActiveAttrib не будет пытаться писать указателю, возвращенному новым вызовом [] с распределением размера 0, но строка не равна нулю. завершено. Затем, позже в коде, строка, отличная от нуля, равна , скопированной в std :: string для хранения, что приводит к переполнению буфера чтения . Очень смущает меня и просто проверяет, может ли std :: string облегчить выполнение.

Эмм ... простите меня, но если это ваша проблема, то все эти решения кажутся слишком сложными.Если проблема сводится к тому, что вы получаете 0 в качестве необходимого размера буфера (это означает, что вы закончите строку, которая не завершена NULL, так как нет места для терминатора NULL), тогда просто убедитесь, что пустое значение терминатор всегда присутствует:

int arraySize; 

/* assume arraySize is set to the length we need */ 
... 

/* overallocate by 1 to add an explicit NULL terminator. Just in case. */ 
char *ptr = malloc(arraySize + 1); 

if(ptr != NULL) 
{ 
    /* zero out the chunk of memory we got */ 
    memset(ptr, 0, arraySize + 1); 

    /* call OpenGL function */ 
    cStyleAPI(ptr, arraySize); 

    /* behold, even if arraySize is 0 because of OpenGL, ptr is still NULL-terminated */ 
    assert(ptr[arraySize] == 0); 

    /* use it */ 
    ... 

    /* lose it */ 
    free(ptr); 
} 

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

+0

Должно быть, самый простой, да. Любопытно: Любая конкретная причина использования 'malloc' &' memset', а не 'calloc'? –

+1

Не совсем - просто привычка. –

+0

Или новый [] и удалить [], если на то пошло? – Joel

Смежные вопросы