read() не работает должным образом в c

#c #io

#c #io

Вопрос:

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

 #include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
    char uselessTable[600];
    int fdInput;
    int firstChar;

    if ((fdInput = open("file.txt", O_RDONLY)) == -1) {
        perror("file");
        _exit(1);
    }

    read(fdInput, amp;firstChar, 1);
    printf("Taille du nom de fichier : %dn", firstChar); // prints 32609

    if (close(fdInput) == -1) {
        perror("close");
        _exit(2);
    }
}
  

Файл содержит строку abc, поэтому он должен печатать число 97, но это не так, если я не удалю таблицу uselessTable, даже если она не используется в этой программе.

Изменение размера таблицы на 500, ее удаление, создание после firstChar или изменение int firstChar на char firstChar, похоже, решает проблему, но я не понимаю почему.

Комментарии:

1. Это потому, что read() перезаписывает только первый байт firstChar int, что приводит к неопределенному поведению. Сделайте firstChar символом char и преобразуйте его в int при использовании printf() для него.

2. Вы считываете один байт в an int (который занимает более одного байта), оставляя другие байты неинициализированными.

Ответ №1:

Давайте пройдемся по этому шаг за шагом. Сначала вы создаете локальную переменную firstChar , которая является an int , а не a char . Локальные переменные, которые не инициализированы (и которые не static инициализированы), могут быть установлены в любое произвольное значение.

Для простоты скажем, что int тип данных на самом деле имеет длину четыре байта.

Следующий шаг заключается в том, что вы считываете одну char переменную в адрес этого четырехбайта int . Итак, в итоге вы получаете память:

             ----- ----- ----- ----- 
firstChar: | 'a' |  ?  |  ?  |  ?  |
            ----- ----- ----- ----- 
  

для первого байта этого int значения установлено значение 97 (при условии ASCII), а для других байтов все еще установлено некоторое произвольное значение.

Поскольку целое число состоит из всех четырех байтов, вот почему вы получаете что-то вроде 32609 .

Очевидным решением является использование char переменной, которая будет использовать только один байт. Таким образом, когда вы перезаписываете этот байт, он будет полностью представлять то, что вы читаете в:

 #include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main() {
    char firstChar = 0xff; // force it so you *know* it changes.
    int fdInput = open("file.txt", O_RDONLY);
    if (fdInput == -1) {
        perror("file");
        _exit(1);
    }

    read(fdInput, amp;firstChar, 1);
    printf("Taille du nom de fichier : %dn", firstChar); // prints 97

    close(fdInput);
}