LINUX.ORG.RU

Ошибки при сборке тренировочного задания по C

 , , , ,


1

2

Есть код на C, для выполнения тренировочного задания: напишите программу для вывода всех строк входного потока, имеющих длину более 80 символов. Вот код: http://ix.io/12jI

Собираю с помощью GCC, вот выхлоп "cc -v"

Using built-in specs.
COLLECT_GCC=cc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.9.2-10' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-arch-32=i586 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.2 (Debian 4.9.2-10)
Получаю ошибки:
hw.c:5:5: error: conflicting types for ‘getline’
 int getline(char line[], int limit);
     ^
In file included from hw.c:1:0:
/usr/include/stdio.h:678:20: note: previous declaration of ‘getline’ was here
 extern _IO_ssize_t getline (char **__restrict __lineptr,
                    ^
hw.c:16:5: error: conflicting types for ‘getline’
 int getline(char line[], int limit) {
     ^
In file included from hw.c:1:0:
/usr/include/stdio.h:678:20: note: previous declaration of ‘getline’ was here
 extern _IO_ssize_t getline (char **__restrict __lineptr,
Не могу понять, что не так. Пожалуйста, помогите разобраться.

★★
Ответ на: комментарий от xaizek

Навроде как у Айсберга была серия книг в духе «Транзистор... это очень просто!»

Прочитал тред, получил удовольствие, еще раз спасибо!

Twissel ★★★★★
()
Ответ на: комментарий от Norong

Правильно ли я понимаю, что порядок размещения переменных в памяти зависит от порядка их объявления?

Правильно для элементов структур, для остального не обязательно.

Кроме того, ты раньше говорил, что локальные переменные размещаются «на стеке». Это какая-то отдельная область памяти, отличная от той, где выделяется место под глобальные переменные?

Ага, та же, которая отвечает за вызовы подпрограмм (передача аргументов через стек может происходить). Глобальные переменные не меняются в размере, поэтому с ними проще. А стек растёт/уменьшается постоянно.

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

Обычно имеет смысл упорядочивать только структуры, которые часто используются (или создаются большие массивы таких структур). В противном случае экономия будет «на спичках». На глобальные переменные и стек никаких гарантий размещения, вроде, нет и компилятор может их перетасовать для экономии памяти самостоятельно (на стеке точно нет, там такое делают давно, а для глобальных не уверен, но вряд ли, оно просто ничего не даёт).

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 4)
Ответ на: комментарий от xaizek

Понял, спасибо!

И ещё один вопрос про scanf и EOF. Я понял так, что если я запрашиваю символ, а там - конец файла, система говорит, что достигнут конец файла, и в поток ставится флаг EOF. Возвращается ли при этом какой-то символ в ответ на запрос? У себя я несколько раз получил числовое значение 0 в той переменной, куда хотел считать символ, но не могу быть уверен, всегда ли будет так, или это неопределённое поведение.

Norong ★★
() автор топика
Последнее исправление: Norong (всего исправлений: 1)
Ответ на: комментарий от Norong

Возвращается ли при этом какой-то символ в ответ на запрос?

Нет, только признак конца.

У себя я несколько раз получил числовое значение 0 в той переменной, куда хотел считать символ, но не могу быть уверен, всегда ли будет так, или это неопределённое поведение.

То случайность, либо ноль было был на стеке, либо scanf() инициализирует переменную сначала. Если эта переменная не в числе тех, которые scanf() смог полностью обработать (скажем, четвёртое, а scanf() вернул 3), то его значение использовать не стоит.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Я прошёл дальше к разделу о файловом вводе/выводе, и у меня возникло несколько вопросов. Не мог бы ты мне их прояснить?

В учбенике написано такое:

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

Дальше в учебнике сказано, что символы для вывода putc накапливаются в буфере, а потом сбрасываются в нужный файл при закрытии файла, которое происходит по fclose или при нормальном завершении программы. Это - тот же буфер, о котором идёт речь в цитате? Если да, то он, получается, либо существует только для файлов, открытых на запись, либо для файлов, открытых на чтение, он имеет другой смысл. Это так? Место под такой буфер, наверное, динамически выделяется malloc'ом по ситуации?

И ещё вопрос: правильно ли я понимаю, что при чтении из stdin я «забираю» из потока символы (и там их больше не остаётся), а при чтении из файла я «продвигаюсь» вперёд по символам?

И ещё: под «нормальным» завершением программы, при котором происходит сброс буфера, понимается завершение по return/exit из main и завершение по exit из любого другого места, или что-то другое?

Заранее спасибо.

Norong ★★
() автор топика
Ответ на: комментарий от Norong

Дальше в учебнике сказано, что символы для вывода putc накапливаются в буфере, а потом сбрасываются в нужный файл при закрытии файла, которое происходит по fclose или при нормальном завершении программы.

Есть разные виды буферизации. При закрытии оно сбрасывается всегда (при нормальном завершении дескрипторы просто закрываются тем же fclose). Но также сбрасывается либо по \n, либо немедленно (т.е. без буферизации). stdout по \n обычно, если не был от терминала.

Это - тот же буфер, о котором идёт речь в цитате? Если да, то он, получается, либо существует только для файлов, открытых на запись, либо для файлов, открытых на чтение, он имеет другой смысл. Это так? Место под такой буфер, наверное, динамически выделяется malloc'ом по ситуации?

Их два. Размер обычно фиксированный (на усмотрение libc), но буфер можно и самому менять. Может динамически, может быть частью FILE на самом деле.

И ещё вопрос: правильно ли я понимаю, что при чтении из stdin я «забираю» из потока символы (и там их больше не остаётся), а при чтении из файла я «продвигаюсь» вперёд по символам?

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

И ещё: под «нормальным» завершением программы, при котором происходит сброс буфера, понимается завершение по return/exit из main и завершение по exit из любого другого места, или что-то другое?

Да, exit по сути. main на самом деле вызывается как exit(main(argc, argv)), так что выход из него эквивалентен вызову exit.

xaizek ★★★★★
()
Ответ на: комментарий от Norong

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

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

stdout по \n обычно, если не был от терминала.

Прошу прощения, я не совсем понял условие «если не был от терминала». Т.е. сброс по \n, если stdout в файл перенаправлен?

Norong ★★
() автор топика
Ответ на: комментарий от Norong

Там слово потерялось при редактировании, «если не был перенаправлен от терминала». Т.е. при выводе в терминал буфер сбрасывается по \n (или явному fflush() или при заполнении буфера, что раньше произойдёт), но если перенаправить в файл или через конвеер, то уже по заполнению буфера (либо fflush). Поэтому иногда перенаправление в файл и вывод потом этого файла на экран может быть быстрее, чем просто вывод на экран.

xaizek ★★★★★
()
Последнее исправление: xaizek (всего исправлений: 1)
Ответ на: комментарий от xaizek

Мне тут в учебнике привели код функции fputs в том виде, в котором он фигурировал в стандартной библиотеке системы авторов. Вот он: https://i.imgur.com/Bs2ivOc.png

Я не очень понимаю, зачем нужен «int c». Мне кажется, можно было легко обойтись без него, просто используя *s++ и *s. Не подскажешь, есть ли в этом «c» какой-то глубинный смысл?

Norong ★★
() автор топика
Последнее исправление: Norong (всего исправлений: 3)
Ответ на: комментарий от xaizek

Кстати, я нередко по ходу учебника видел, что хотя подразумевается помещение в переменную символа, используют тип int. Это, наверное, из-за того, что char может быть беззнаковым, и в таком случае в него не удастся поместить EOF?

Norong ★★
() автор топика
Ответ на: комментарий от Norong

EOF в char равно символу '\xff' и их невозможно отличить. Так как int может хранить все значения что и char, но больше, то для работы с символами в stdio используется int, как раз чтобы можно было кодировать EOF без опасности пересечься с настоящим символом '\xff'.

xaizek ★★★★★
()
Ответ на: комментарий от Norong

есть ли в этом «c» какой-то глубинный смысл?

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

Да и код концептуально проще — всегда можно считать, что s всегда указывает на текущий символ, а не на следующий, если перед этим было *s++.

i-rinat ★★★★★
()
Ответ на: комментарий от Norong

В int это 0xffffffff (для sizeof(int) == 4), а в char 0xff и при правильном расширении до int оно будет 0x000000ff (правильное это с преобразованием к unsigned char, иначе будет 0xffffffff из-за расширения знакового разряда).

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

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

#include <stdio.h>
#include <string.h>

#define LIMIT 200

int main(int argc, char *argv[])
{
    char string1[LIMIT], string2[LIMIT];
    FILE *fp1, *fp2;

    fp1 = fopen(argv[1], "r");
    fp2 = fopen(argv[2], "r");

    do {
        fgets(string1, LIMIT, fp1);
        printf("%s", string1);
        fgets(string2, LIMIT, fp2);
        printf("%s", string2);

        if (strcmp(string1, string2) != 0) {
            printf("%s: %s\n%s: %s\n", argv[1], string1, argv[2], string2);
            return 0;
        }
    } while(!feof(fp1) && !feof(fp2));
    return 0;
}
Код работает не совсем корректно. Если файлы совпадают за исключением того, что один файл длиннее, например:
file1:
первая строка
вторая строка
третья строка
последняя строка
file2:
первая строка
вторая строка
третья строка
то неверно выводится та строка из второго файла, которая отличается от строки с тем же номером первого файла. При таких входных данных я ожидал вывод:
file1: последняя строка
file2: 
, но получаю
file1: последняя строка
file2: третья строка

В своих предположениях я исходил из приведённого в учебнике кода fgets: https://i.imgur.com/UbiubwU.png После того, как считаны третьи строки, я захожу в цикл ещё раз. Для первого файла fgets запишет в string1 «последняя строка», а для второго, как я понимаю, getc вернёт EOF, и '\0' должен быть записан в нулевую позицию string2. Тем не менее, этого не происходит. Не подскажешь, что я делаю не так?

И ещё: флаг EOF ставится в поток после того, как я считаю оттуда последний символ, или же при попытке считать что-то сверх последнего символа?

Norong ★★
() автор топика
Ответ на: комментарий от Norong

В своих предположениях я исходил из приведённого в учебнике кода fgets

В man fgets явно не сказано о неизменности массива (просто, мол '\0' ставится после последнего считанного символа, а EOF это не считанный символ). В стандарте более явно:

7.19.7.2 The fgets function
... If end-of-file is encountered and no characters have been read into the array,
the contents of the array remain unchanged and a null pointer is returned. ...
Так что эту ситуацию надо самому обрабатывать.

И ещё: флаг EOF ставится в поток после того, как я считаю оттуда последний символ, или же при попытке считать что-то сверх последнего символа?

Второй вариант.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Я в учебнике прочитал описания двух функций, и не совсем понял пару моментов.

Функция ungetc. Помещает символ «c» назад в файл «fp» и возвращает либо «c», либо EOF в случае ошибки. Для каждого файла гарантирован возврат только одного символа.

Как происходит «возврат» символа в файл в случае работы с обычным файлом и в случае с stdin? Раньше в учебнике была реализована функция, выполняющая схожую роль, она записывала символы в отдельный буфер, а для чтения символов использовалась функция-обёртка над этим буфером и над обычным getchar(). И не совсем ясно про «гарантирован возврат только одного символа». Как я понимаю, это значит, что один символ я в любом случае смогу вернуть в файл. А что может мне помешать вернуть больше, и чем обусловлена гарантия?

Дальше:

Функция free(p) освобождает участок памяти, на который указывает указатель p. ... Порядок освобождения выделенных участков памяти не регламентируется. Однако если указатель не был получен с помощью malloc или calloc, то его освобождение является грубой ошибкой. Обращение по указателю после его освобождения - также ошибка. <дальше пример правильного освобождения связанного списка> В разделе 8.7 показана реализация функции распределения памяти наподобие malloc, в которой выделенные блоки можно освобождать в любом порядке.

Тут не понял про особенности, связанные с порядком. Если я выделил несколько областей памяти и на каждую имею указатель, я же могу их в любом порядке обратно высвобождать, вроде. Или здесь речь именно о том, чтобы не потерять указатель на другую область при высвобождении, например, того же связанного списка? В раздел 8.7 заглянул, там о том, что

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

Там ещё много текста, но, вроде, основная мысль в этом.

Ну и тут есть одно задание:

Такие функции, как isupper, можно реализовать с позиций экономии времени, а можно с позиций экономии места. Исследуйте обе возможности.

isupper же - функция проверки, является ли аргумент функции символом в верхнем регистре. Мне приходит в голову один единственный способ такой проверки: if (c >= A && c <= Z). Вроде, он настолько примитивный, что тут ни время не тратится, ни память. Чего ждёт от меня автор?

Пожалуйста, помоги мне разобраться с этими вопросами. Заранее большое спасибо.

Norong ★★
() автор топика
Последнее исправление: Norong (всего исправлений: 1)
Ответ на: комментарий от Norong

Как происходит «возврат» символа в файл в случае работы с обычным файлом и в случае с stdin? Раньше в учебнике была реализована функция, выполняющая схожую роль, она записывала символы в отдельный буфер, а для чтения символов использовалась функция-обёртка над этим буфером и над обычным getchar().

Так и происходит, но уже внутри реализации стандартной библиотеки.

И не совсем ясно про «гарантирован возврат только одного символа». Как я понимаю, это значит, что один символ я в любом случае смогу вернуть в файл. А что может мне помешать вернуть больше, и чем обусловлена гарантия?

Ограниченный размер буфера и помешает. При отсутствии свободного места, символы больше не будут приниматься и ungetc вернёт ошибку.

Тут не понял про особенности, связанные с порядком. Если я выделил несколько областей памяти и на каждую имею указатель, я же могу их в любом порядке обратно высвобождать, вроде. Или здесь речь именно о том, чтобы не потерять указатель на другую область при высвобождении, например, того же связанного списка?

О том, что порядок вызовов free не должен повторять или быть обратным порядку вызовов malloc. Не знаю, зачем именно они это тут уточняют (это для стека важен порядок, но с ним напрямую в C не работают).

Мне приходит в голову один единственный способ такой проверки: if (c >= A && c <= Z). Вроде, он настолько примитивный, что тут ни время не тратится, ни память. Чего ждёт от меня автор?

Детали, конечно, зависят от архитектуры, но условные переходы вещь не бесплатная и от них бывают избавляются (ну и это для английского в ASCII, для других кодировок проверки могут быть изощрённее; EBCDIC, например, неудобна в этом смысле была). Так что это с позиции экономии памяти. Как сделать с противоположной позиции и так, чтобы было без переходов, должно быть несложно догадаться.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

О том, что порядок вызовов free не должен повторять или быть обратным порядку вызовов malloc.

Т.е. он должен быть каким угодно, но не прямым и не обратным?

Не знаю, зачем именно они это тут уточняют (это для стека важен порядок, но с ним напрямую в C не работают).

А для меня, как для пишущего код, это, получается, не имеет значения? А в каком случае имеет?

условные переходы вещь не бесплатная и от них бывают избавляются
так, чтобы было без переходов

Могу так: return (c >= A && c <= Z) или return (isupper(c) == c), но есть сомнения. Первый вариант из этого сообщения от варианта с if-ом отличается разве что тем, что я не проверяю значение этого логического выражения, а сразу его возвращаю, да и всё ещё зависимо от кодировки. Второй вариант, вероятно, дороже, ибо isupper тоже в себе что-то содержит.

Norong ★★
() автор топика
Ответ на: комментарий от Norong

Т.е. он должен быть каким угодно, но не прямым и не обратным?

Нет. Это было отрицание необходимости соблюдения дополнительных условий. Главное это освобождать память один раз и не обращаться к ней потом.

А для меня, как для пишущего код, это, получается, не имеет значения? А в каком случае имеет?

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

Могу так: return (c >= A && c <= Z) или return (isupper(c) == c), но есть сомнения. Первый вариант из этого сообщения от варианта с if-ом отличается разве что тем, что я не проверяю значение этого логического выражения, а сразу его возвращаю, да и всё ещё зависимо от кодировки. Второй вариант, вероятно, дороже, ибо isupper тоже в себе что-то содержит.

И без сравнений тогда ещё, так как их может понадобиться много. А можно не делать эти проверки во время исполнения, а сделать иначе. У char всего 256 возможных значений.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

про память

Т.е. ситуация такова, что в большинстве случаев нет разницы, в каком порядке выделять/освобождать память, если только я сначала её выделяю, потом использую, освобождаю и больше не использую. Именно это и имелось в виду под:

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

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

Ага?

И без сравнений тогда ещё, так как их может понадобиться много. А можно не делать эти проверки во время исполнения, а сделать иначе. У char всего 256 возможных значений.

Может быть, заранее составить список кодов подходящих букв, и искать в этом списке мой код?

Norong ★★
() автор топика
Последнее исправление: Norong (всего исправлений: 1)
Ответ на: комментарий от Norong

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

Ага?

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

Может быть, заранее составить список кодов подходящих букв, и искать в этом списке мой код?

Вроде того. Но тут смотря как этот список и поиск в нём будут организованы.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Спасибо, про память всё понял!

Вроде того. Но тут смотря как этот список и поиск в нём будут организованы.

Создать массив, пронумерованный символьными кодами больших букв, и при получении символа «c» попытаться обратиться к элементу с номером «c»? Должно быть быстро, но я не знаю, как произвольно пронумеровать массив.

Norong ★★
() автор топика
Ответ на: комментарий от Norong

Создать массив, пронумерованный символьными кодами больших букв, и при получении символа «c» попытаться обратиться к элементу с номером «c»?

Да. Только главное про возможную знаковость char не забыть.

Должно быть быстро, но я не знаю, как произвольно пронумеровать массив.

Можно просто создать массив на 256 элементов. Есть же и другие is*() функции, каждый элемент каким-то свойством да обладает. В C89 иных вариантов особо и нет (кроме вычисления таблицы единожды при первом вызове или её генерации другой программой с последующей вставкой в исходники). В C99 добавили designated initializers и можно делать так:

char array[] = {
    ['A'] = 1,
    ['B'] = 1,
    ...
};
Можно реализовать, просто вычислив таблицу один раз и вызвав проверку несколько раз.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Да. Только главное про возможную знаковость char не забыть.

Это как раз в случае, если я создаю вручную массив на 256 персон? Если беззнаковый, то нумерую от 0 до 255, иначе - от -128 до 127, и делать выбор надо будет самому в зависимости от системы, так? И в те элементы, которым соответствуют большие буквы, пишу 1, остальные инициализируются нулями. Тогда можно сходу return array['c'], наверное. Если хочу хранить разные свойства - можно каждый элемент массива сделать структурой с битовыми полями. Или структурой с переменными, если места не жалко.

В C99 добавили designated initializers и можно делать так

Я правильно понимаю, что отличие от того, что есть в C89, заключается в том, что я могу не просто указывать инициализирующие значения, но и помещать их в нужные мне элементы?

Можно реализовать, просто вычислив таблицу один раз и вызвав проверку несколько раз.
В C89 иных вариантов особо и нет (кроме вычисления таблицы единожды при первом вызове или ...

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

Norong ★★
() автор топика
Ответ на: комментарий от Norong

Это как раз в случае, если я создаю вручную массив на 256 персон? Если беззнаковый, то нумерую от 0 до 255, иначе - от -128 до 127, и делать выбор надо будет самому в зависимости от системы, так?

Просто преобразовывать к unsigned char и помнить, что 128 элемент это -128 и т.д.

Я правильно понимаю, что отличие от того, что есть в C89, заключается в том, что я могу не просто указывать инициализирующие значения, но и помещать их в нужные мне элементы?

Да.

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

Ага. Но тогда будет проверка на то, что вызов первый. Так что это как вариант, чаще всю таблицу просто готовят заранее.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Просто преобразовывать к unsigned char и помнить, что 128 элемент это -128 и т.д.

Т.е. достаточно делать массив от -128 до 127, и преобразовывать к unsigned char счётчик (при заполнении) и номер символа (при поиске)? Вроде, он тогда сам преобразуется из 128 в -128, мне даже помнить об этом не надо будет.

Norong ★★
() автор топика
Ответ на: комментарий от Norong

Т.е. достаточно делать массив от -128 до 127, и преобразовывать к unsigned char счётчик (при заполнении) и номер символа (при поиске)?

Да. В общем, главное не обратиться к элементам до начала массива и значения для отрицательных char'ов правильно разместить.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

А в чём тут есть подводные камни? У меня же при приведении к unsigned char всё равно любому коду символа будет поставлен в соответствие номер в массиве, и даже порядок, в сущности, значения не имеет. Или я что-то не так понимаю?

И, кажется, я постом выше ошибся: если приводим к unsigned, то массив как раз 0..255.

Norong ★★
() автор топика
Последнее исправление: Norong (всего исправлений: 1)
Ответ на: комментарий от Norong

А в чём тут есть подводные камни? У меня же при приведении к unsigned char всё равно любому коду символа будет поставлен в соответствие номер в массиве, и даже порядок, в сущности, значения не имеет. Или я что-то не так понимаю?

Вообще это было о заполнении массива вручную и приведении во время индексирования. Если заполнять в коде и с приведением, то всё будет хорошо.

xaizek ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.