LINUX.ORG.RU

Ответ на: комментарий от AptGet

Я согласен. Если бы я писал свою книгу по C то я не стал бы там в примере с Hello World проверять код возврата printf. Потому что в этой программе если произошла какая-то ошибка с выводом строки - пользователь (программист, осваивающий C) это заметит по тому, что строка не вывелась.

tim239 ★★
()

почему-то никто не вспомнил про

#error "hello world"

nanoolinux ★★★★
()
Ответ на: комментарий от jtootf
class Coro : public Generator<char>
{
	void proceed()
	{
		const char *p = "Hello, World!\n";
		while (*p)
			yield(*p++);
	}
};


int main()
{
	Coro obj;
	char c;
	while (obj(c))
	{
		putchar(c);
	}
}
anonymous
()
Ответ на: комментарий от anonymous

Эталонная хелло-ворлд жесть!

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

Вопрос к плюсокодерам - вы правда юзаете спецификаторы private и protected при объявлении субкласса (class className : protected superclass)? Какой-то ад и майндфак.

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

правда это означает не «есть разновидность» (public) а «реализован посредством» (private,protected) private от protected отличается тем хочеш ты производным от тебя классам дать доступ к интерфейсам твоего базового класса (protected) или только к своим (private) вообще саттер пишет «реализован посредством» лучше создавать включением а не наследованием если только не надо переопределить виртуальную функцию или получить доступ к protected членам

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

но вообще то логичней если приперло наследовать от почки человека из за необходимости переопределить виртуальные функции почки или получить доступ к ее защищенным членам то лучше создать промежуточный класс «улучшенная почка» в нем все переопределить потрогать защищенные члены а потом уже этот промежуточный класс (улучшенную почку) просто включить как член человека без взякого извращения (типа наследования почки от челоека)

это вроде тоже саттер писал

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

Если почка наследуется от человека, то с архитектурой полный ахтунг. Возвращаясь к вопросу, куда понятнее же сначала занаследовать, а уже потом переопределить с сокрытием, например. Ну да ладно, не я язык создавал, не мне судить.

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

asm() директива вставки ассебмлера. Прекрасно работает и без volatile. volatile указывает что блок нельзя оптимизировать и перемещать в другие места.

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

мнемокод эквивалент машкода поэтому в мнемокоде и нет символьных(с возможно говорящими) меток

ассемблер(a1) всё таки не всегда после трансляции в машкод(m1) и обратного дизасемблирование(a2) получает тоже текстовое представление (a1!=a2)

повтороное a2->m2(==m1)->a3(==a2)

т.е не всякий ассемблерный код(ибо при трансляции теряется семантика символьных имён) обладает вами указаным свойством но всякий дизасемблированный(ибо вновь создаваемых имён автоматически детерминирована).

qulinxao ★★☆
()

отвечает след. правилам:

  • 1. единый стиль расстановки фигурных скобок(предпочитаю «стиль Алмена)
  • 2. единый стиль расстановки пробелов - 4(не используя табуляцию).
  • 3. не использовать след. идентификаторы(в связи с расширяемостью ANSI C)
    • E[0-9]* E[A-Z]* is[a-z]* LC[A-Z]* mem[a-z]*
    • NDEBUG Offsetof raise SIG[A-Z]* str[a-z]*
    • to[a-z]* wcs[a-z]* _*
  • 4. обязательное использование комментариев(блочный в заголовке, с описанием модуля, и по ходу кода)
  • 5. в соответствии со стандартом С99, пункт 5.1.2.2.1 - только int main (void){return 0} или int main (int argc, char *argv[]){return 0}
/*
*Пишем идеальный
*Hello World на Cи
*/
include <stdio.h>
include <string.h>

int main(int argv, int *argc[])
{
/*Cтрока вывода как кому нравится*/
    char *cStr = "Hello World.";
    int iC;/*значения желательно всегда инициализировать*/
    int iStrLen = (int)strlen(cStr);/*в реальности не стоит так делать*/
    char *pcStr = *cStr;

    printf("%s\n", cStr);
    printf("Hello World.\n");

/*Для извращенцев только!
текст проги должен быть понятен
с первого взгляда*/
    for (iC = 0, iC < iStrLen, iC++, pcStr++)
    {
        printf("%c", *pcStr);
    }/*for*/
    printf("\n");
 
   return 0;
}
juniorroy
()
Ответ на: комментарий от juniorroy

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

qulinxao ★★☆
()

http://www.ioccc.org/years-spoiler.html#1984_anonymous
вполне полезный для развития понимания языка пример hello_word-программы
зы. современые компиляторы не проверяет семантику идентификатора на соответствие с выполняемыми с_ним|им действиями.
следовательно со временем происходит увеличение зазора между семантикой имени и семантикой обьекта с этим именем.

qulinxao ★★☆
()
Ответ на: комментарий от vaino

это не С

Вот си:

/*
 * X86-64 C hello world.
 */

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

int get_byte(int word, int byte)
{
    return (word >> (byte << 3)) & 0xFF;
}

enum reg {
    rax = 0xc0,
    rdx = 0xc2,
    rsi = 0xc6,
    rdi = 0xc7
};

/* class Emitter */

char *buf;
int cp = 0, size = 0;

/* private: */

void emit_char(char ch)
{
    buf[cp++] = ch;
}

void emit_int(int n, int val)
{
    for (int i = 0; i < n; ++i)
        buf[cp++] = get_byte(val, i);
}

/* public: */

// Emitter
void init_emitter(size_t size_)
{
    size = size_;
    buf = calloc(size, sizeof(char));
}

// ~Emitter
void free_emitter(void)
{
    free(buf);
}

void mov(enum reg r, int val)
{
    emit_char(0x48);
    emit_char(0xc7);
    emit_char(r);
    emit_int(4, val);
}

void syscall(void)
{
    emit_char(0x0f);
    emit_char(0x05);
}

void execute(void)
{
    (*(void(*)())buf)();
}

void show(void)
{
    for (int i = 0; i < size; ++i)
        printf("%02x ", buf[i]);

    puts("");

    fflush(stdout);
}

/* e.g. */

// .rodata:
const char hw[] = "Hello, World!\n";

// .text:
int main(void)
{
    init_emitter(50);

    mov(rax, 1);
    mov(rdi, 1);
    mov(rsi, hw);
    mov(rdx, 14);
    syscall();

    mov(rax, 60);
    mov(rdi, 7);
    syscall();

    show();

    execute();

    free_emitter();
}
$ gcc -std=c99 -o hw hw.c && execstack -s hw
hw.c: In function ‘main’:
hw.c:91:5: warning: passing argument 2 of ‘mov’ makes integer from pointer without a cast
hw.c:50:6: note: expected ‘int’ but argument is of type ‘const char *’
$ ./hw                                        
48 ffffffc7 ffffffc0 01 00 00 00 48 ffffffc7 ffffffc7 01 00 00 00 48 ffffffc7 ffffffc6 23 0a 40 00 48 ffffffc7 ffffffc2 0e 00 00 00 0f 05 48 ffffffc7 ffffffc0 3c 00 00 00 48 ffffffc7 ffffffc7 07 00 00 00 0f 05 00 00 00 00 
Hello, World!
quasimoto ★★★★
()
Ответ на: комментарий от nickionn

Это ваш с++ не нужен.

Уж получше вашего Си будет

Беги, Никита, беги без оглядки.

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

разметку запорол

скорее всего должно быть так

void main(void)
nickionn ★☆
()
Ответ на: комментарий от anonymous

я уже молчу про «return 0»

Заполни мой пробел в знаниях, что не так с return 0?

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

gcc добавит же ☺

Вот такой файл

main(){printf("Hello, world!\n");}
хоть и компилируется с предупреждением, но работает.

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

И действительно: бинарник возвращает что угодно (после каждой перекомпиляции что-то новое).

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

Вот си:

$ ./a.out 
48 ffffffc7 ffffffc0 01 00 00 00 48 ffffffc7 ffffffc7 01 00 00 00 48 ffffffc7 ffffffc6 ffffffd3 09 40 00 48 ffffffc7 ffffffc2 0e 00 00 00 0f 05 48 ffffffc7 ffffffc0 3c 00 00 00 48 ffffffc7 ffffffc7 07 00 00 00 0f 05 00 00 00 00 
Segmentation fault
vaino
()
Ответ на: комментарий от quasimoto

У меня тоже сегфолт на 64-битной системе.

Кстати, у тебя еще и в исходниках ошибки. С человеческим -Wall -Werror не скомпилится. Значит - не нужно.

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

Какая архитектура? x86-64?

да, кстати к чему такие сложности с execstack?

mprotect(buf, size_, PROT_EXEC | PROT_READ);

и не надо костылей

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

У меня тоже сегфолт на 64-битной системе.

Почему? Выполнение на стеке/в куче включил?

Кстати, у тебя еще и в исходниках ошибки

Это потому что я const char [15] как int передаю (чтобы адрес hw взять). Как исправить?

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

С учётом разработки даже раньше.
В вики это называют GNU style, но в отличие от него, у Plan 9
for(...) {
т.е без переноса на новую строку скобки не функций.
Числовые константы принято определять через enum.
http://code.google.com/p/plan9front/source/browse/sys/src/9/pc/sdide.c — типичный пример.

quantum-troll ★★★★★
()
Ответ на: комментарий от vaino

Добавил

mprotect(buf, size, PROT_EXEC | PROT_READ | PROT_WRITE);

в конец init_emitter - теперь у меня сегфолт. Делаю опять

execstack -s hw

и снова работает.

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

как?

Мне execstack(8) хватило. Вот ещё mprotect(2) советуют.

4 байта == 32 бита, а надо 64 бита.

Там mov берёт 4 байта из слова (int), так что адрес в hw в .rodata должен быть меньше 2 ^ 32 - у меня так, так что я не стал более общее поведение писать.

Можно попробовать проще:

    mov(rax, 60);
    mov(rdi, 7);
    syscall();

это exit(7).

quasimoto ★★★★
()

после ручной компиляции в basic C получается:

int i;main(){
    for(;
        *("]<i;++i){--i;}\0"+i);
        write(1,i++ +"hello, world!\n",1)
       );
}
qulinxao ★★☆
()
Ответ на: комментарий от Eddy_Em

-Wall -Werror

- mov(rsi, hw);
+ mov(rsi, (int)hw);

clang пропускает, gcc - нет :)

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

буфер надо выделять через memalign

Да, теперь заработало.

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

K&R, похоже, доработали свой стиль, пока разрабатывали Plan 9.

quantum-troll ★★★★★
()
Ответ на: комментарий от quasimoto
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <malloc.h>
#include <sys/mman.h>

typedef uint8_t u8;

/* An executable buffer. */

typedef struct {
    size_t size;
    size_t cp;
    u8 *buf;
} Emitter;

Emitter* make_emitter(size_t size)
{
    Emitter *em = malloc(sizeof(Emitter));
    em->size = size;
    em->cp = 0;
    em->buf = valloc(size * sizeof(u8));
    memset(em->buf, 0, size);
    mprotect(em->buf, size, PROT_EXEC | PROT_READ | PROT_WRITE);
    return em;
}

void free_emitter(Emitter *em)
{
    free(em->buf);
    free(em);
    em = NULL;
}

void emitter_error(const char *message)
{
    fprintf(stderr, "%s\n", message);
    exit(EXIT_FAILURE);
}

void emitter_error_overflow(void)
{
    emitter_error("emitter overflow");
}

/* x86-64. */

typedef uint32_t u32;
typedef uint64_t u64;

u8 get_u8(u8 n, u64 x)
{
    return (x >> (n << 3)) & 0xFF;
}

typedef enum {
    rax = 0xc0,
    rcx = 0xc1,
    rdx = 0xc2,
    rbx = 0xc3,
    rsp = 0xc4,
    rbp = 0xc5,
    rsi = 0xc6,
    rdi = 0xc7,
    r8 = 0xc000,
    r9 = 0xc100,
    r10 = 0xc200,
    r11 = 0xc300,
    r12 = 0xc400,
    r13 = 0xc500,
    r14 = 0xc600,
    r15 = 0xc700,
} Reg;

void emit_u8(Emitter *em, u8 x)
{
    if (1 + em->cp < em->size) {
        em->buf[em->cp] = x;
        em->cp++;
    } else {
        emitter_error_overflow();
    }
}

void emit_u32(Emitter *em, u32 x)
{
    if (4 + em->cp < em->size) {
        for (int i = 0; i < 4; i++) {
            em->buf[em->cp] = get_u8(i, x);
            em->cp++;
        }
    } else {
        emitter_error_overflow();
    }
}

void emit_u64(Emitter *em, u64 x)
{
    if (8 + em->cp < em->size) {
        for (int i = 0; i < 8; i++) {
            em->buf[em->cp] = get_u8(i, x);
            em->cp++;
        }
    } else {
        emitter_error_overflow();
    }
}

void mov(Emitter *em, Reg reg, u64 x)
{
    if (reg < r8) {
        emit_u8(em, 0x48);
        if (x <= 0xFFFFFFFF) {
            emit_u8(em, 0xc7);
            emit_u8(em, reg);
            emit_u32(em, x);
        } else {
            emit_u8(em, reg - 8);
            emit_u64(em, x);
        }
    } else {
        emit_u8(em, 0x49);
        if (x <= 0xFFFFFFFF) {
            emit_u8(em, 0xc7);
            emit_u8(em, get_u8(1, reg));
            emit_u32(em, x);
        } else {
            emit_u8(em, get_u8(1, reg) - 8);
            emit_u64(em, x);
        }
    }
}

void nop(Emitter *em)
{
    emit_u8(em, 0x90);
}

void syscall(Emitter *em)
{
    emit_u8(em, 0x0f);
    emit_u8(em, 0x05);
}

void execute(Emitter *em)
{
    (*(void(*)())em->buf)();
}

void show(Emitter *em)
{
    for (int i = 0; i < em->size; i++)
        printf("%02x ", em->buf[i]);

    puts("");

    fflush(stdout);
}

const char hw1[] = "Hello, World!\n";

int main(void)
{
    char hw2[] = "Hello, World!\n";

    printf("hw1 = %p, hw2 = %p\n", hw1, hw2);

    Emitter *e = make_emitter(100);

    mov(e, rax, 1);
    mov(e, rdi, 1);
    mov(e, rsi, (u64)hw1);
    mov(e, rdx, 14);
    syscall(e);

    mov(e, rax, 1);
    mov(e, rdi, 1);
    mov(e, rsi, (u64)hw2);
    mov(e, rdx, 14);
    syscall(e);

    mov(e, rax, 60);
    mov(e, rdi, 7);
    syscall(e);

    show(e);

    execute(e);

    free_emitter(e);
}
$ clang -Wall -Werror -std=c99 -o hw hw.c
$ gcc -Wall -Werror -std=c99 -o hw hw.c  
$ ./hw                                   
hw1 = 0x400fd8, hw2 = 0x7fff40441d80
48 c7 c0 01 00 00 00 48 c7 c7 01 00 00 00 48 c7 c6 d8 0f 40 00 48 c7 c2 0e 00 00 00 0f 05 48 c7 c0 01 00 00 00 48 c7 c7 01 00 00 00 48 be 80 1d 44 40 ff 7f 00 00 48 c7 c2 0e 00 00 00 0f 05 48 c7 c0 3c 00 00 00 48 c7 c7 07 00 00 00 0f 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
Hello, World!
Hello, World!
$ echo $?
7

Правда выйти из выполнения buf не получается (если не делать exit(7) - падает).

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

Правда выйти из выполнения buf не получается (если не делать exit(7) - падает)

Надо, видимо, дописать jmp и делать jmp из buf куда-нибудь обратно в main или просто на другую функцию.

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