后续跟进学习了c++ runtime libarary,不幸的是vs2019 msvc工具不允许我重载库函数,故编译无法通过,不过学习MiniCRT PLUS还是学习到了很多知识,也熟悉了c++ 的string库,io库实现原理。
由于是基于MiniCRT的PLUS版本,故只贴上新增源码:
iostream.h
#include "minicrt.h"
namespace std
{
class ofstream
{
protected: // protect : can be access by its child class, but not other class.
FILE* fp;
ofstream(const ofstream&);
public:
enum openmode{in = 1 ,out = 2, binary = 4, trunc = 8};
ofstream();
explicit ofstream(const char* filename,ofstream::openmode md = ofstream::out);
~ofstream();
ofstream& operator<<(char c);
ofstream& operator<<(int n);
ofstream& operator<<(cosnt char* str);
ofstream& operator<<(ofstream& (*)(ofstream&));
void open(const char* filename,ofstream::openmode md = ofstream::out);
void close();
ofstream& write(cosnt char* buf,unsigned size);
};
inline ofstream& endl(ofstream& o) // inline: suggest compiler this function do not have own stack. Like the #define.
{
return o << '\n';
}
class stdout_stream: public ofstream
{
public:
stdout_stream();
};
extern stdout_stream cout;
}
// static: when the static decorate a global variable or function, it means that this can only be used in this file.
minicrt.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
//malloc
#ifndef NULL
#define NULL (0)
#endif
void free(void* ptr);
void* malloc(int size);
int mini_crt_init_heap();
//string
char* itoa(int n,char* str,int radix);
int strcmp(const char* src,const char* dst);
char* strcpy(char* dest,const char* src);
int strlen(const char* str);
//file & IO
typedef int FILE;
#define EOF (-1)
#define stdin ((FILE*)(GetStdHandle(STD_INPUT_HANDLE)))
#define stdout ((FILE*)(GetStdHandle(STD_OUTPUT_HANDLE)))
#define stderr ((FILE*)(GetStdHandle(STD_ERROR_HANDLE)))
int mini_crt_init_io();
FILE* fopen(const char* filename,const char* mode);
int fread(void* buffer,int size,int count,FILE* stream);
int fwrite(const void* buffer, int size, int count, FILE* stream);
int fclose(FILE* fp);
int fseek(FILE* fp, int offset, int set);
//printf
int fputc(int c, FILE* stream);
int fputs(const char* str, FILE* stream);
int printf(const char* format, ...);
int fprintf(FILE* stream,const char* format,...);
//internal
void do_global_ctors();
void mini_crt_call_exit_routine();
//atexit
typedef void (*atexit_func_t)(void);
int atexit(atexit_func_t func);
#ifdef __cplusplus
}
#endif
ctors.cpp
typedef void(*init_func)(void);
#pragma section(".CRT$XCA",long,read)
#pragma section(".CRT$XCZ",long,read)
__declspec(allocate(".CRT$XCA")) init_func ctors_begin[] = { 0 };
__declspec(allocate(".CRT$XCZ")) init_func ctors_end[] = { 0 };
extern "C" void do_global_ctors()
{
init_func* p = ctors_begin;
while (p < ctors_end)
{
if (*p != 0)
(**p)();
p++;
}
}
iostream.cpp
#include "minicrt.h"
#include "iostream"
#include <windows.h>
namespace std
{
stdout_stream::stdout_stream():ofstream()
{
fp = stdout;
}
stdout_stream cout;
ofstream::ofstream():fp(0)
{
}
ofstream::ofstream(const char* filenameofstream::openmode md):fp(0)
{
open(filename,md);
}
ofstream::~ofstream()
{
close();
}
ofstream& ofstream::operator<<(char c)
{
fputc(c,fp);
return *this
}
ofstream& ofstream::operator<<(int n)
{
fprintf(fp,"%d",n);
return *this;
}
ofstream& ofstream::operator<<(const char* str)
{
fprintf(fp,"%s",str);
return *this
}
ofstream& ofstream::operator<<(ofstream& (*manip)(ofstream&))
{
return manip(*this);
}
void ofstream::open(const char* filename,ofstream::openmode md)
{
char mode[4];
close();
switch(md)
{
case out | trunc:
strcpy(mode,"w");
break;
case out|in|trunc:
strcpy(mode,"w+");
case out|trunc|binary:
strcpy(mode,"wb");
break;
case outin|trunc|binary:
strcpy(mode,"wb+");
}
fp = fopen(filename,mode);
}
void ofstream::close()
{
if(fp)
{
fclose(fp);
fp = 0;
}
}
ofstream& ofstream;:write(const char* buf,unsigned size)
{
fwrite(buf,1,size,fp);
return *this;
}
}
new_delete.cpp
extern "C" void* malloc(unsigned int);
extern "C" void free(void*);
void* operator new (unsigned int size)
{
return malloc(size);
}
void operator delete(void* p)
{
free(p);
}
void* operator new[](unsigned int size)
{
return malloc(size);
}
void operator delete[](void* p)
{
free(p);
}
string
namespace std
{
class string
{
int len;
char* pbuf;
public:
explicit string(const char* str); // explicit: deny class construct implicit convert.
string(const string&);
~string();
string& operator=(const string&);
string& operator=(const char* s);
const char& operator[](unsigned idx) const;
char& operator[](unsigned idx);
const char* c_str() const;
unsigned length() const;
unsigned size() const;
};
string::string(const char* str):
len(0),pbuf(0)
{
*this = str;
}
string::string(const string& s)
{
*this = s;
}
string::~string()
{
if(pbuf != 0)
{
delete[] pbuf;
pbuf = 0;
}
}
string& string::operator=(const string& s)
{
if(&s == this)
return *this;
this->~string();
len = s.len;
pbuf = strcpy(new char[len+1],s.pbuf);
return *this;
}
string& string::operator=(const char* s)
{
this->~string();
len = strlen(s);
pbuf = strcpy(new char[len+1],s);
return *this;
}
const char& string::operator[](unsigned idx) const
{
return pbuf[idx];
}
char& string::operator[](unsigned idx)
{
return pbuf[idx];
}
const char* string::c_str() const
{
return pbuf;
}
unsigned string::length() const
{
return len;
}
unsigned string::size() const
{
return len;
}
ofstream& operator<<(ofstream& o,const string& s)
{
return o << s.c_str();
}
}
compile.bat
@echo off
VsDevCmd.bat
cl /c /DWIN32 /GS- entry.c malloc.c formatstr.c stdio.c string.c atexit.c
cl /c /DWIN32 /GS- /GR- ctors.cpp new_delete.cpp iostream.cpp
lib entry.obj malloc.obj formatstr.obj stdio.obj string.obj ctor.obj new_delete.obj atexit.obj iostream.obj /OUT:minicrt.lib
vcvars32.bat
cl /c /DWIN32 /GR- test.cpp
link main.obj minicrt.lib kernel32.lib /NODEFAULTLIB /entry:mini_crt_entry