Получают ли строки адрес памяти, если они объявлены, но не инициализированы? Мне нужна помощь, чтобы понять некоторые странные в упражнении восстановления данных - PullRequest
0 голосов
/ 08 апреля 2020

Итак, я нахожусь в процессе восстановления. c pset для CS50, и я настроил свой код так, чтобы он просто печатал, каким будет имя файла, когда он видит заголовок jpeg (например, «000.jpg \ n001» .jpg ").

Следующий код дал странные результаты:

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

void writeJPG(char *file_name, int file_num);

int main(int argc, char *argv[])
{
    //check for valid inputs
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    FILE *file = fopen(argv[1], "r");
    if (file == NULL)
    {
        printf("file could not be opened\n");
        return 1;
    }

    int file_num = 0;
    char file_name[7];

    typedef uint8_t BYTE; //define BYTE type

    BYTE test[512];
    BYTE *test_p = test;

    int a = fread(test_p, 512, 1, file);
    do
    {
        for (int k = 0; k < 512; k++)
        {
            a = fread(test_p+k, 1, 1, file);
        }

        if (test[0] == 0xff && test[1] == 0xd8 && test[2] == 0xff)
        {
            if (test[3] >= 0xe0 && test[3] <= 0xef)
            {
                writeJPG(file_name, file_num);
                printf("%s\n", file_name);
                file_num++;
            }
        }

        /*for(int i = 0; i < 512; i++)
        {
            //if (*(test_p + i) != 0)
            //{
                printf("%i ", *(test_p + i));
            //}
        }
        //printf("%i\n", *test_p);
        printf("\n\n");*/
        //a = fread(test, 1, 1, file);

    }
    while (a == 1);
}

void writeJPG(char * file_name, int file_num)
{
    //char file_name[7];
    //file_name[0] = '\0';
    if (file_num < 10)
    {
        sprintf(file_name, "00%i.jpg", file_num);
    }
    else if (file_num < 100)
    {
        sprintf(file_name, "0%i.jpg", file_num);
    }
    else if (file_num < 1000)
    {
        sprintf(file_name, "%i.jpg", file_num);
    }
    //return file_name;
}

вывод: https://i.imgur.com/1sYu2jc.png

рабочий код:

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

void writeJPG(char *file_name, int file_num);

int main(int argc, char *argv[])
{
    //check for valid inputs
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        return 1;
    }

    FILE *file = fopen(argv[1], "r");
    if (file == NULL)
    {
        printf("file could not be opened\n");
        return 1;
    }

    int file_num = 0;
    char file_name[] = "000.jpg";

    typedef uint8_t BYTE; //define BYTE type

    BYTE test[512];
    BYTE *test_p = test;

    int a = fread(test_p, 512, 1, file);
    do
    {
        for (int k = 0; k < 512; k++)
        {
            a = fread(test_p+k, 1, 1, file);
        }

        if (test[0] == 0xff && test[1] == 0xd8 && test[2] == 0xff)
        {
            if (test[3] >= 0xe0 && test[3] <= 0xef)
            {
                writeJPG(file_name, file_num);
                printf("%s\n", file_name);
                file_num++;
            }
        }

        /*for(int i = 0; i < 512; i++)
        {
            //if (*(test_p + i) != 0)
            //{
                printf("%i ", *(test_p + i));
            //}
        }
        //printf("%i\n", *test_p);
        printf("\n\n");*/
        //a = fread(test, 1, 1, file);

    }
    while (a == 1);
}

void writeJPG(char * file_name, int file_num)
{
    //char file_name[7];
    //file_name[0] = '\0';
    if (file_num < 10)
    {
        sprintf(file_name, "00%i.jpg", file_num);
    }
    else if (file_num < 100)
    {
        sprintf(file_name, "0%i.jpg", file_num);
    }
    else if (file_num < 1000)
    {
        sprintf(file_name, "%i.jpg", file_num);
    }
    //return file_name;
}

output: https://i.imgur.com/XmsB22w.png

Единственное, что отличается в рабочем коде, это то, что строка file_name инициализирована как "000.jpg". Мне нужна помощь, чтобы понять, почему этот работает, и почему исходный плохой код все еще увеличивался один раз, а затем останавливался.

Спасибо!

1 Ответ

0 голосов
/ 08 апреля 2020

char file_name[]; не является правильным определением. Поскольку это объявление нарушает правило в C 2018 6.7 7 («Если идентификатор объекта объявлен без привязки, тип объекта должен быть завершен к концу его декларатора,…»), поведение не определяется стандартом C.

Как ни странно, это правило не отображается в ограничении и, по-видимому, не требует сообщения c о диагностике в соответствии с правилами стандарта C. Однако любой порядочный C компилятор выдаст вам сообщение об ошибке. Убедитесь, что предупреждения и сообщения об ошибках для вашего компилятора включены, и обратите на них внимание.

Вы можете зарезервировать пространство для file_name, указав размер для массива, например char file_name[1000];. Похоже, вашей программе потребуется только определенное количество места для имени файла. Вы должны рассчитать это максимальное пространство, включая завершающий нулевой символ, и зарезервировать столько места или больше.

...