2013-05-21 2 views
0

Вот фрагмент кода. Я использую g ++Угадайте выход. (Объявление/инициализация массива символов)

void initialize(int p, char a[], char b[]) 
{ 
    for(int i=0;i<6*p;i++) 
    { 
     a[i]='-'; 
     b[i]='-'; 
    } 
} 

int main() 
{ 
    int p=9; 
    char a[2*p],b[4*p]; 
    initialize(p,a,b); 
    cout<<a<<endl<<b<<endl; 
} 

Здесь описываются способы a и b ... они должны быть размером 18 и 36 соответственно. Но они не видны на выходе. Что происходит?

Output: 
------------------------------------------------------ 
------------------------------------------------------------------------------------------------------ 

ответ

0
char a[2*p] will have 2*9=18 characters max. 
char b[4*p] will have 4*9=36 characters max. 

инициализация создает 6 * 9 = 54 символов, но каждый объект принимает в пределах своего предела. Что вы здесь делаете?

+0

Точно. Я хотел инициализировать с 18, b с 36 «тире». Но тогда b имел значения мусора после 36-го тире, которое выглядело как – Nikhil

+0

Я не вижу их в своем браузере: | – Discipol

2

Вы инициализацией далеко за пределы памяти вы выделили для a и b

Вы должны сделать

for(int i = 0; i < 2*p; ++i) { 
    a[i]='-'; 
} 

for(int i = 0; i < 4*p; ++i) { 
    b[i]='-'; 
} 

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

+1

Мне нравится идея отправки по факсу моей собаки. –

+0

При инициализации в границах он отображает значения мусора для некоторого большего пространства за его пределами. Поэтому. – Nikhil

+0

@Nikhil: Мусор за его пределами должен быть отменен. См. Ответ raj raj или мой собственный для получения дополнительной информации – Jimbo

0

Ваш for цикл:

for(int i=0;i<6*p;i++) 

Лакомства размер массива, как 6*p, где в примере p==9. Таким образом, ваша петля рассматривает размер массива как 54.

Но массив a имеет только 18 элементов, поэтому ваша инициализация переполняет этот массив.

Array b имеет только 36 элементов, поэтому ваша инициализация переполняет этот массив.

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

Вы бы лучше использовать такую ​​функцию. Также вам нужно NULL-terminate ваши строки?

void initialize(char a[], size_t aSize, char b[], size_t bSize) 
{ 
    int i = 0; 
    for(; i < aSize-1; i++) 
     a[i]='-'; 
    for(i = 0; i < bSize-1; i++) 
     b[i]='-'; 

    // I think you need to NULL terminate.... 
    a[aSize-1] = '\0'; 
    b[bSize-1] = '\0'; 
} 

int main() 
{ 
    int p=9; 
    char a[2*p],b[4*p]; 
    initialize(a, sizeof(a), b, sizeof(b)); 

    std::cout << a << std::endl << b << std::endl; 
    return 0; 
} 

Или еще более обобщенно в вас main() функции, если вы когда-либо использовать массивы, которые не типа char ...

initialize(a, sizeof(a)/sizeof(a[0]), b, sizeof(b)/sizeof(b[0])); 

Или даже, чтобы инициализировать массивы просто использовать memset(), а затем вам не понадобится функция initialize() :)

Например

#include <string.h> 

int main() 
{ 
    int p=9; 
    char a[2*p],b[4*p]; 

    memset(a, '-', sizeof(a)-1); 
    a[sizeof(a)-1] == '\0'; 
    memset(b, '-', sizeof(b)-1); 
    b[sizeof(b)-1] == '\0'; 

    std::cout << a << std::endl << b << std::endl; 
    return 0; 
} 

Другой вещь, которую я только что хотя был «вы NULL оконечного ваших строк? Я изменил примеры выше для удовлетворения, что, в противном случае при печати строки функция печати не будет знать, где остановиться!

Еще один вариант может также быть std::fill() или *std::fill_n()*:

#include <iostream> 
#include <algorithm> // std::fill 

int main(int argc, char* argv[]) 
{ 
    int p=9; 
    char a[2*p],b[4*p]; 

    std::fill_n(a, sizeof(a)-1, '-'); 
    a[sizeof(a)-1] = '\0'; 

    std::fill_n(b, sizeof(b)-1, '-'); 
    b[sizeof(b)-1] = '\0'; 

    std::cout << a << std::endl << b << std::endl; 
    return 0; 
} 
0

Вывод, что вы получите только потому, что вы не нулевой Прекратить строки. Возможно, вы не получите тот же результат, который у вас есть, если вы поместите свой код другим способом. Просто вы начали инициализацию массивов из-за границы, и как-то оба массива лежали рядом друг с другом, и cout искал следующий '\0' до того места, где он печатался.

Только нуль-конец массива, и тогда все в порядке.

+0

raj, у него также есть проблемы с переполнением массива, это не просто нулевое завершение, вызывающее проблемы – Jimbo

+0

Да, но он получает такие длительные выходы из-за того, что не завершает его, не так ли? И доступ к массивам за пределами границ никогда не рекомендуется. –

+0

Да, нулевое завершение создает ошибки длины, но «просто нуль-конец массива, и все в порядке». Не совсем верно, потому что у него все еще есть потенциально довольно неприятная ошибка, что не так:) – Jimbo

Смежные вопросы