Hello world с пустой функцией main

Рейтинг: 317Ответов: 12Опубликовано: 19.01.2011

Столкнулся с такой задачей на собеседовании:

Написать программу, которая печатает в консоли фразу Hello world

И всё бы ничего, если бы после этого стояла точка. Но фраза продолжается:

при условии, что функция main() данной программы выглядит следующим образом:

int main() 
{
    return 0;
}

Ответы

▲ 314Принят

Ответ очень прост. Их даже несколько. Самый простой, основанный на свойстве глобальных статических объектов.

int printHelloWorld() { printf("Hello World"); return 0; }
static int testVar = printHelloWorld();
int main ()
{
    return 0;
}

Это, если С стиль. С++ стиль: создаем класс, в конструкторе добавляем вывод, будет вывод до main, в деструкторе - после.

▲ 209

Используем препроцессор.

#define return puts("Hello World"); return

int main ()
{
  return 0;
}

Не такой красивый вариант как со статикой, но тоже работает.

▲ 110

True programmer напишет это в hex редакторе в машинных кодах. Даже функция main не нужна.

BB 11 01 B9 0D 00 
B4 0E 8A 07 43 CD 
10 E2 F9 CD 20 48 
65 6C 6C 6F 2C 20 
57 6F 72 6C 64 21

Немного исправим, воспользовавшись примером выше для соответствию заданию.

using namespace std;
#include<ofstream>

class hello{
public:
hello()
{
    ofstream hello;
    hello.open ("hello.com");
    hello << "»..№..ґ.Љ.CН.вщН Hello, World!";
    hello.close();
    system("hello.com");
}put;

int main(){
    return 0;
}

Вуаля мы получили программу на языке С++ которая возвращает .com файл, затем запускает его, после чего этот файл через BIOS прерывание выводит на экран Hello, world! При этом наша программа имеет пустую функцию main и не обращается напрямую к стандартном выводу в командную строку. Работает только в DOS command promt.

▲ 100

Статические переменные и дефайны не обязательны:

#include <cstdio>
int s = printf("Hello world\n");

int main()
{
    return 0;
}
▲ 76

Вот ещё способ:

#include <stdio.h>

void hello()
{
    puts("Hello, World!");
}
#pragma data_seg(".CRT$XIY")
void(*pinit)()=&hello;

int main()
{
    return 0;
};

Только оказалось, что он только в дебаге работает.

ПРАВКА:

А ещё можно подменить точку входа:

#pragma comment(linker, "/ENTRY:Main") //Вместо прагмы можно использовать параметр командной строки
#include <windows.h> //CRT с его printf и puts (не говоря уже о cout) мы, к сожалению, потеряли, поэтому придётся использовать средства ОС

int main(void) 
{
    return 0;
}

void Main()
{
    WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), "Hello, World!\n", 14, nullptr, nullptr);
}

Кстати, у меня эта программка занимает 656 байт после того, как я немного похимичил с ключами компиляции.

▲ 74
#include<iostream>

class hello {
    public:
        hello(){ std::cout << "Hello, world!\n"; }
} put;

int main(){
    return 0;
}
▲ 65
#include <iostream>

const std::ostream& out = std::cout << "Hello World" << std::endl;
▲ 55

Помимо многих предложенных ранее вариантов с выводом текста до выполнения main, предложу вариант с выводом после выполнения main:

#include <cstdio>
#include <cstdlib>

void hw() {
    puts("Hello world");
}

int v = atexit(hw);

int main() {
    return 0;
}
▲ 49

gcc поддерживает атрибут "constructor", который помещает функцию в init-секцию ELF-файла. Что, в свою очередь, означает, что эта функция вызовется перед функцией main. То есть, то, что нам нужно.

void __attribute__((constructor)) init {
  printf("Hello world!");
}
▲ 26
$ cat hellower.cpp 
#include "helper.cpp"
int main(void) {
        return 0;
}

второй файл:

$ cat helper.cpp 
#include <stdio.h>

int hello_helper() {
        printf("Hello World\n");
        return 0;
}

static int a = hello_helper();

Лаунч:

$ g++ hellower.cpp
$ ./a.out 
Hello World
▲ 24

Первый файл (строго соответствует условию задачи):

$ cat main.cpp
int main(void)
{
    return 0;
}

Второй файл:

$ cat hello.cpp
#include <stdio.h>

int hello_helper() {
    printf("Hello World\n");
    return 0;
}

static int a = hello_helper();

Makefile для компилятора g++:

$ cat makefile
TARGET = hello
PREFIX = /usr/local/bin
.PHONY: all clean install uninstall
all: $(TARGET)
clean:
    rm -f $(TARGET) *.o
main.o: main.cpp
    g++ -c -o main.o main.cpp
hello.o: hello.cpp
    g++ -c -o hello.o hello.cpp
$(TARGET): main.o hello.o
    g++ -o $(TARGET) main.o hello.o
install:
    cp $(TARGET) $(PREFIX)/$(TARGET)
uninstall:
    rm -f $(PREFIX)/$(TARGET)
▲ 14

Вот в стиле C++

#include <iostream>

class StaticOutput
{
    static int print();
    static int out;
};

int StaticOutput::out = StaticOutput::print();

int StaticOutput::print()
{
    std::cout << "Hello World!" << std::endl;
    return 0;
}


int main()
{
    return 0;
}