2015-02-25 2 views
1

Моя программа продолжает производить ошибку сегментации. я упростил свой код на следующее:C++ files array messes up my variable

#include <stdio.h> 

void open_file(FILE** file) 
{ 
     *file = fopen("test" , "wb"); 
     return; 
} 


int main() 
{ 
    int Tracks = 1; 
    FILE* Files; 
    int i = 1; 

    Files = new FILE[Tracks + 1]; 

    printf("i = %d\n", i); //i = 1 
    open_file(&Files + i); 

    printf("i = %d\n", i); /i = 0 
    fclose(*(&Files + i)); //Segmentation fault 

    return 0; 
} 

я должен делать некоторые действительно глупое указатель ошибки, но мне мои операции указатель арифметика выглядеть хорошо ... Проблема заключается в том, что по какой-то причине волшебной , переменная i меняет свое значение на 0. Может ли кто-нибудь объяснить мне, почему?

Заранее благодарен!

+1

Вы должны удалить 'FILE * Files'. И отредактируйте 'FILE ** Files = new ...' – ForceBru

+2

Выглядит больше как C, чем C++ (кроме 'new'). – crashmstr

+0

@crashmstr, в чем ваш смысл? Это все еще C++. – dfeuer

ответ

2

fopen возвращает ФАЙЛ *, поэтому вы можете использовать массив FILE * или FILE ** для хранения многих из них.

Также вы должны проверить файл, который нужно открыть перед закрытием.

#include <stdio.h> 

void open_file(FILE** file) 
{ 
    *file = fopen("test" , "wb"); 
    return; 
}  

int main() 
{ 
    int Tracks = 1; 
    FILE** Files = new FILE*[Tracks + 1]; 
    int i = 1; 

    printf("i = %d\n", i); //i = 1 
    open_file(&Files[i]); // Will write at the address of the i-th element of Files. 

    printf("i = %d\n", i); //i = 1 

    // This have to be done for each element that correspond to an open file. 
    // Add a for-loop should be considered. 
    if (Files[i])   // Avoid segmentation fault 
    { 
     fclose(Files[i]); 
     Files[i] = 0;  // So I know it is closed. 
    } 

    delete[] Files; 
    return 0; 
} 

О Files[i] = 0; вы посмотрите here может.

Об магияi модификация. Вот что происходит:

void open_file(FILE** file) 
{ 
    // Write file address or 0 at the given address. 
    *file = fopen("test" , "wb"); 
    return; 
}  

int main() 
{ 
    int Tracks = 1; 
    FILE* Files = new FILE[Tracks + 1]; // Files at address a 
    int i = 1;       // i probably at address a + sizeof(FILE*) 

    printf("i = %d\n", i); // i = 1 

    // here i = 1 so &Files + i = &Files + 1 = address of i. 
    open_file(&Files + i); // Call to open_file with the address of i ! 

    // open_file failed and write 0 to the given address. 
    printf("i = %d\n", i); // i = 0 
} 
+0

Спасибо за ваш просветительский ответ! –

+0

просто еще один вопрос, это как я должен удалить указатель-массив: delete [] * Files; –

+0

@HeinrichHeine, действительно, вы должны удалить ** полный массив **, например: 'delete [] Files;'. Каждый элемент массива должен быть закрыт. – Orace

4

Проблема заключается в operator precedence, где адрес оператора имеет более высокий приоритет, чем оператор сложения. Это означает, что вы делаете, например. (&Files) + i, что эквивалентно (&Files)[i].

+0

Это неправильно в любом случае. (& Files) [i] неверен, потому что только i = 0 действителен. & Files [i] неверно, потому что это приведет к несоответствию типа. Этот ответ неверен. Тип (& Files) [i] и тип & Files [i] различны. Проблема в том, что вся программа запутана. Почему в мире open_file не просто возвращает FILE * ... Также нет необходимости в новом FILE. fopen делает это для вас. – thang

+0

Он (неявным образом) отвечает, почему переменная i может быть изменена. – stefaanv

+0

@stefaanv, это не так. Ответ на вопрос, почему я могу изменить, состоит в том, что (& Files) [1] указывает на адрес памяти, занимаемый i. Я подозреваю, что оригинальный плакат знает, что & Files + i совпадает с (& Files) [i]. Это должно быть супер неявным ... – thang