Как избежать использования константы для размера файла? - PullRequest
0 голосов
/ 05 октября 2019

Кажется, что стандартная практика программирования и стандарт POSIX противоречат друг другу. Я работаю с программой и заметил, что вижу много таких вещей, как:

char buf[NAME_MAX + 1]

И я также вижу, что многие операционные системы не определяют NAME_MAX и говорят, чточто с технической точки зрения они не должны это делать в соответствии с POSIX, потому что вы должны использовать pathconf для получения значения, к которому оно настроено во время выполнения, а не жестко кодировать его как константу в любом случае.

Проблема в том, чтокомпилятор не позволит мне использовать pathconf таким образом с массивами. Даже если я попытаюсь сохранить результат pathconf в const int, он все равно выбрасывает и говорит, что должен быть константой. Таким образом, похоже, что для того, чтобы на самом деле использовать pathconf, мне бы пришлось избегать использования массива символов для буфера здесь, потому что это явно недостаточно. Так что я застрял между молотом и наковальней, потому что стандарт C ++, по-видимому, не позволяет мне делать то, что POSIX говорит, что я должен делать, то есть определять размер символьного буфера для имени файла во время выполнения, а не во время компиляции.

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

std::vector<char> buf((pathconf("/", _PC_NAME_MAX) + 1));

И затем я могу определить размер, вызвав buf.size() или что-то еще. Но я не уверен, что это правильный подход вообще. У кого-нибудь есть опыт попытки остановить программу в зависимости от того, какие константы, такие как NAME_MAX или MAXNAMLEN определены в системных заголовках, и заставить реализацию использовать вместо нее pathconf во время выполнения?

1 Ответ

0 голосов
/ 06 октября 2019

На полпути меры имеют тенденцию приводить к каким-либо конфликтам.

const usigned NAME_MAX = /* get the value at runtime */;
char buf[NAME_MAX + 1];

Во второй строке объявляется массив в стиле C (предположительно), предназначенный для хранения строки в стиле C. В С это нормально. В C ++ существует проблема, потому что значение NAME_MAX не известно во время компиляции. Вот почему я назвал это промежуточной мерой - здесь есть смесь кода в стиле C и компиляции C ++. (Некоторые компиляторы допускают это в C ++. По-видимому, ваш не позволяет.)

Подход C ++ будет использовать строки в стиле C ++, как в:

std::string buf;

Вот и все. Размер указывать не нужно, так как память будет распределяться по мере необходимости, если вы избегаете интерфейсов в стиле C. Используйте потоковую передачу (>>), когда это разумно. Если буфер заполняется пользовательским или файловым вводом, это должно быть все, что вам нужно.


Если вам нужно использовать строки в стиле C (возможно, этот буфер заполняется системным вызовом, написанным дляC?), Есть несколько вариантов выделения необходимого пространства. Самым простым, вероятно, является вектор, очень похожий на тот, о котором вы думали.

std::vector<char> buf{NAME_MAX + 1};
system_call(buf.data()); // Send a char* to the system call.

В качестве альтернативы вы можете использовать строку в стиле C ++, которая может сделать манипулирование данными более удобным.

std::string buf{NAME_MAX + 1, '\0'};
system_call(buf.data()); // Send a char* to the system call.

Существует также опция интеллектуального указателя, но подход vector может сыграть лучше с существующим кодом, написанным для массива в стиле C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...