C: строковый литерал в массив int

У меня есть функция, принимающая в качестве аргумента массив int. Массив int представляет собой строку, но должен содержать EOF и поэтому не может иметь тип char[]. Моя функция выглядит примерно так:

_Bool fun(int str[]) {
  // does something involving checking elements for EOF, e.g.:
  return (str[0]==EOF);
}

В целях тестирования я хотел бы вызвать fun со строковым литералом (хотя, естественно, строковый литерал имеет тип char[] и не сможет содержать EOF), в действительности:

fun("test");

который будет компилироваться, но с предупреждениями о неправильном типе аргумента. Это ожидаемо, поскольку строковый литерал — char[], а аргумент — int[].

Я мог бы сделать это:

fun( (int*) "test");

что, вероятно, эквивалентно, просто я делаю приведение явно, те же предупреждения компиляции.

Я читаю, что приведение char* к int* не гарантирует работу (ссылка). Что в общем случае естественно, так как если я сейчас попытаюсь записать большое int в str[some_index], то оно может не поместиться - str[some_index] имеет память, выделенную только под char (скажите, если я ошибаюсь).

Но так как я не буду делать никаких подобных записей, а просто сравню (и сравнение char и int должно быть в порядке) - я в порядке с любым из вышеперечисленных? Как в этом случае избавиться от предупреждений компиляции? Или как лучше это решить?

Конечно, я мог бы написать простую функцию для копирования массива char, который дает строковый литерал, в массив int, значение за значением, но должен быть лучший способ. Такое решение также приведет к пустой трате памяти.

(Кстати - при тестировании с EOF я сделаю примерно так:

int str[] = {'t', 'e', 's', 't', EOF};
fun(str);

который должен работать нормально.)


person Carl    schedule 30.12.2012    source источник
comment
Зачем вам использовать EOF в строке? Это делает жизнь чрезмерно сложной по сравнению с использованием '\0' для обозначения конца строки.   -  person Jonathan Leffler    schedule 30.12.2012
comment
Это ваша типичная строка, которая может заканчиваться нулем, или она содержит двоичные данные?   -  person goji    schedule 30.12.2012
comment
@JonathanLeffler: я отправляю EOF в fun для тестирования. fun в противном случае работает со стандартным вводом, так что это имеет смысл. @ Трой, не понимаю твоего вопроса. Но поскольку fun предназначен для работы с данными из стандартного ввода, он обычно не будет двоичным.   -  person Carl    schedule 30.12.2012
comment
Какую проблему вы пытаетесь решить, что предложило эту технику в качестве реализации?   -  person EvilTeach    schedule 30.12.2012
comment
@EvilTeach: приведенный выше код, конечно, очень сокращен, но fun() читает из stdin с помощью getchar(), и я хочу протестировать fun() с помощью своей среды модульного тестирования. При тестировании getchar() заменяется другой функцией, которая вместо этого считывает символы из массива, который я могу предоставить из своих процедур тестирования. Могут появляться не только значения char, но и EOF, для которых требуется int. Вот почему мне нужно использовать массив int для символов.   -  person Carl    schedule 30.12.2012
comment
если fun читает из стандартного ввода, то нет необходимости передавать массив int для его обработки. что-то вне функции должно читать, а забава должна просто обрабатывать это. это позволит вам исключить предположение о том, что EOF возможен. Это позволит вам вернуться к использованию массивов символов. Если аргумент представляет собой массив символов, проблема с модульным тестом становится тривиальной.   -  person EvilTeach    schedule 30.12.2012
comment
@EvilTeach: мне просто нужно проверить что-то, читающее со стандартного ввода, где может появиться EOF, и я сделаю это, читая из предоставленного массива вместо стандартного ввода. Как именно организованы функции и что они делают, это другой вопрос, код, который я предоставил, является сокращением, чтобы показать принцип.   -  person Carl    schedule 30.12.2012
comment
@EvilTeach: в реальном случае fun читает из стандартного ввода с помощью getchar(), но при тестировании fun вместо этого читает из предоставленного int[]. Независимо от того, как я организую функции, при тестировании необходимо предоставить искусственную последовательность целых чисел, предоставленную мной, которая будет считываться вместо чтения со стандартного ввода, и мне все равно нужно будет определить эту последовательность в моих процедурах тестирования. Я хотел бы иметь возможность использовать строковые литералы и EOF в этой последовательности, чтобы она имитировала стандартный ввод. Поэтому я все еще вижу необходимость в возможности комбинировать строковый литерал со значением EOF и передавать его в fun.   -  person Carl    schedule 30.12.2012


Ответы (3)


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

Предполагая, что вы используете машину с прямым порядком байтов (Intel), функция ожидает такой макет памяти (где пустые квадраты содержат все нулевые биты):

+---+---+---+---+
| t |   |   |   |
+---+---+---+---+
| e |   |   |   |
+---+---+---+---+
| s |   |   |   |
+---+---+---+---+
| t |   |   |   |
+---+---+---+---+
|EOF|EOF|EOF|EOF|
+---+---+---+---+

То, что вы передаете, представляет собой макет памяти, подобный этому:

+---+---+---+---+
| t | e | s | t |
+---+---+---+---+
| \0| 
+---+

Что совсем не одно и то же. Это полностью игнорирует вероятные проблемы с выравниванием; вы передаете 5 байтов данных без маркера EOF, чтобы отметить конец строки.

Короче говоря, не делайте этого!

person Jonathan Leffler    schedule 30.12.2012
comment
Это был мой первый вопрос: могу ли я сделать актерский состав таким образом?, и вы очень четко ответили «нет» и объяснили, почему, спасибо. Но тогда для меня важнее вопрос: как мне добиться того, чего я хочу? Является ли написание моей собственной функции для преобразования строкового литерала (char[]) в int[] единственным способом? - person Carl; 30.12.2012
comment
@Карл: Да; нет другого способа сделать преобразование из строкового литерала в целочисленный массив, чем функция D.I.Y. Писать не очень сложно, но необходимо. Если вы где-нибудь упомянули широкие символы, вы могли бы вместо этого использовать функции манипулирования широкими символами, но ваш вопрос касается только int. - person Jonathan Leffler; 30.12.2012

Хорошо, итог:

Подразумеваемое или явное приведение (fun("test") и fun( (int*) "test") соответственно) не будет делать то, что я хочу (подробности см. в ответе Джонатана Леффлера).

Способ пойти здесь, вероятно, состоит в том, чтобы написать какую-то пользовательскую функцию, которая объединит строковый литерал со значением EOF и вернет все это как int[].

person Carl    schedule 01.01.2013

Попробуйте сравнить с 0, потому что EOF является определением 0, а эквивалент char равен '\ 0'

person Camille Tolsa    schedule 30.12.2012
comment
Я только когда-либо видел, что EOF определяется как -1. - person goji; 30.12.2012
comment
Не думайте так. Насколько я знаю, EOF не может быть представлен как char. Я читал, что EOF обычно определяется как -1, как пишет Трой. \0 — это символ завершения строки, и это не то же самое, что EOF. - person Carl; 30.12.2012
comment
EOF не является синонимом 0, если только, если я действительно неправильно не прочитал этот ответ, я думаю, что вы путаете EOF с NULL. - person WhozCraig; 30.12.2012