LINUX.ORG.RU

Почему такой вывод строки работает?

 ,


0

1

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

#include <iostream>

int main()
{
    const char ca[] = {'h','e','l','l','o'}; // Строка *без* \0  в конце
    const char *cp = ca;
    while (*cp) {
        std::cout << *cp << std::endl;
        ++cp;
    }
    return 0;
}

Вывод:

h
e
l
l
o

Дело в том, что если бы я массив ca[] инициализировал не явно (как в примере), а с помощью строкового литерала, то, да, в конце должен был бы быть символ \0 и всё должно бы было работать, как выше. Но почему и здесь оно работает? (про std::string и прочее знаю, интересует именно подход в данном случае и строки в стиле С).

Ну, лежит (случайно) ноль на стеке после строки по адресу ca+6, делов-то...

anonymous
()

Случайный ноль в нужном месте.

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

Ну, я предполагал, как минимум вывода кучи «мусорных» символ в консоль. А тут всё тихо и безболезненно.

GreenBag ★★
() автор топика

потому что у тебя всего 5 символов, а компилятор выравнивает стек, поэтому он будет как минимум выровнен по границе 4 байт для 32 битной архитектуры и 8 байт для 64 битной архитектуры.

Попробуй массив из ровно 4, 8 или 16 символов

Harald ★★★★★
()

У меня выводит мусор после строки с gcc-2.95.

С gcc-4 действительно мусор пропадает.

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

Ну, я предполагал, как минимум вывода кучи «мусорных» символ в консоль. А тут всё тихо и безболезненно.

Запустил твой пример, выводит мусор в конце. Почему такая разница - тебе уже объяснили.

obinos
()
Ответ на: комментарий от Harald

Да, действительно, с 4мя символами появлися мусор. Но, если честно, я таки не понял, как это связанно с выравниванием стэка.

GreenBag ★★
() автор топика

Попробовал gcc 4.7, 4.6 и 4.4. Во всех случаях в конце мусор.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от obinos

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

main:
.LFB966:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp ; вот тут под массив hello и указатель сp выделяется сразу 16 байт
        movb    $104, -16(%rbp); пишем 'h'
        movb    $101, -15(%rbp); 'e'
        movb    $108, -14(%rbp); 'l'
        movb    $108, -13(%rbp); 'l'
        movb    $111, -12(%rbp); 'o'
        leaq    -16(%rbp), %rax
        movq    %rax, -8(%rbp)
        jmp     .L2

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

Компилятором, для выравнивания.

Прошу прощения, но я не понимаю, с какой целью надо вбивать в память на стеке нули для выравнивания? Какой от этого профит? Или просто немного лишнего процессорного времени убить?

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

Буду благодарен за ссылку на компилятор, который так делает.

Делает как? Если стандартом что то не описано, то это compiler specific.

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