2017-01-01 3 views
45

У меня есть массив из 16 байтов, который содержит имя сегмента исполняемого файла.Является ли законным передавать строку с нулевым завершением в strncmp в C?

char segname[16]; 

Если длина имени сегмента меньше 16 байт, то остальные заполняются нулевыми байтами. В противном случае не будет завершающий нулевой байт.

Я хочу сравнить segname с различными строками, например. __text.

Можно ли назвать strncmp линией с нулевым завершением?

This post предполагает, что это является законным. This source code также делает его законным. Но страница моего человека говорит:

strncmp() функция лексикографически сравнивает нулевые байты s1 и s2.

Размер, указанный в strncmp будет размером segname.

Мне интересно, на что я должен ссылаться.

+19

Массив 'char', который не' '\ 0''-terminated, не является строкой! – Olaf

+9

@Olaf В следующий раз я назову его «возможно, с нулевым завершением массива». – Bilow

+0

Вы пропустили мою мысль! Строкового типа в C. Нет, вы должны рассмотреть возможность потратить лишний символ 'char' и всегда завершать массив. Это позволяет использовать другие строковые функции. Береженого Бог бережет! – Olaf

ответ

66

Согласно стандарту C99, раздел 7.21.4.4, § 3, это законно:

strncmp функция возвращает целое гр чем, равный или меньше нуля, соответственно, так как , возможно, нулевой конец, массив, на который указывает s1, больше, равный или меньше, чем , возможно, нулевая матрица, на которую указывает s2.

Обратите внимание, что в нем указано массив символов. По определению, если массив символов не имеет нулевого конца, то это не строка.

+10

C99 был заменен; C2011 - это текущий стандарт C. Его спецификация для 'strncmp()' в разделе 7.24.4.4, действительно, опускает любое требование о том, что массивы, которые будут сравниваться, заканчиваются на нуль. –

+9

Следует, однако, заметить, что отсутствие требования о завершении нулевого значения не допускает доступа за пределы любого входного массива. На вызывающем абоненте должно быть гарантировано, что третий аргумент уместен, чтобы избежать функции, перекрывающей границы любого массива. Вызывающий не может вызвать неопределенное поведение, если он этого не сделает. –

+1

@JohnBollinger: Когда стандарт указывает, что символы, следующие за нулевым байтом, не сравниваются, следует ли предположить, что реализация будет вести себя так, как будто она не читает таких символов? Вряд ли показалось бы необычным, что приложению может потребоваться сравнить нулевую заполненную строку [которая может не иметь конечного нуля, если она точно заполняет свой буфер], с нулевым концом [чей буфер может быть короче, чем у нулевых строка], и такая гарантия понадобится, чтобы сделать strncmp подходящим для этой цели. – supercat

14

Функция strncmp сравнивает не более п символов (символы , которые следуют за нулевой символ не сравниваются) из массива указал на S1, в массив, на который указывает s2.

Спецификация 7.24.4.2 говорит, что. C11 стандарт.

Символы, которые не следуют за нулевыми символами, не сравниваются, поэтому они ожидают нулевой символ или строку символов.

Вы можете использовать не-нуль символов тоже здесь, но в этом случае мы должны указать длину ДО, которую мы имеем, чтобы проверить это, которое полезно в некоторых случаях.

Исправление


[1] Это символы, которые не следует нулевому символу, не сопоставляется не означает, что strncmp ожидает неопределенные байт. Это просто означает, что strncmp нуждается в специальном случае, чтобы сказать (например), что abc\0def ... и abc\0xyz ... сравните равные.Там нет ничего плохого в сравнении двух полукокса массивов, которые не являются завершающим нулем (до указанной длины) или сравнивая один нуль массива символов с другой, не оканчивающимся нулем
Это добавляется непосредственно из . комментарий David Hammen

+4

Примечание «... следуйте NULL charcaters ....» имеет больше смысла как «... следовать за нулевым символом ...». 'NULL' - постоянная константа указателя_, связанная с указателями. Сохраните прописную букву «NULL» для обсуждения указателей. – chux

+0

Или вы можете написать NUL, как это обычно обозначается в стандартах ASCII и ASCII. – giusti

+0

@giusti C не указывается для использования ASCII, но обычно это делает. Вот почему 'NUL' (определенное значение ASCII) не используется в спецификации C (за исключением ненормативной сноски.) Хорошей альтернативой _нутому символу является' '\ 0''. См. [This] (http://stackoverflow.com/a/15479382/2410359) – chux

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