如何解决缩小C程序的大小以适合qr代码
我想将minesweeper放入一个qr代码中,该代码最大允许容量为3KB。就目前而言,我程序的二进制文件为12KB,其目标文件为3KB。我尝试在二进制文件上使用UPX,并设法将其压缩到6KB。我一直在使用以下命令进行编译:
gcc.exe -Wall -Os -ffunction-sections -fdata-sections -c C:\Users\mlfre\OneDrive\Desktop\Minesweeper2\main.c -o obj\Release\main.o
和gcc.exe -o bin\Release\Minesweeper2.exe obj\Release\main.o -s -Wl,--gc-sections -lKernel32 -lgcc -lmsvcrt
。
我没有尝试删除默认库,因为每当我这样做时,都会遇到很多未定义的引用错误,并且尝试了许多方法,但是每个“解决方案”都带来了更多的问题。我还没有尝试编辑PE标头,因为它们看起来很复杂,而且我还没有找到足够低的解释。尽管确实确保将过去的头文件限制为windows.h
。我知道我需要的库是kernel32
,因为大多数都需要它,mscvrt
是Windows.h的库,gcc
是因为如果我使用-nodefaultlibs,它将被删除。
我的代码可以在这里看到
#include <windows.h>
#define WIDTH 100
#define HEIGHT 100
#define BOMBS 800
struct xorshift_state {
int a;
};
int xorshift(struct xorshift_state *state)
{
int x = state->a;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return state->a = x;
}
void ExpandGrid(int fullGrid[WIDTH][HEIGHT],int knownGrid[WIDTH][HEIGHT],int blankPos[2])
{
int neighbors[8][2] = {{0,1},{1,0},{0,-1},{-1,-1}};
int curTile[2];
knownGrid[blankPos[0]][blankPos[1]] = 1;
if(fullGrid[blankPos[0]][blankPos[1]] != 0) return;
for(int blck = 0; blck < 8; ++blck)
{
curTile[0] = blankPos[0]+neighbors[blck][0];
curTile[1] = blankPos[1]+neighbors[blck][1];
if(curTile[0] > WIDTH-1 || curTile[1] > HEIGHT-1 || curTile[0] < 0 || curTile[1] < 0) continue;
if(fullGrid[curTile[0]][curTile[1]] == 0 && knownGrid[curTile[0]][curTile[1]] == 0)
{
knownGrid[curTile[0]][curTile[1]] = 1;
ExpandGrid(fullGrid,knownGrid,curTile);
}
else if(fullGrid[curTile[0]][curTile[1]] > 0) knownGrid[curTile[0]][curTile[1]] = 1;
}
}
int main(int argc,char *argv[])
{
COORD characterBufferSize = { WIDTH,HEIGHT };
COORD characterPosition = { 0,0 };
SMALL_RECT consoleWriteArea = { 0,WIDTH - 1,HEIGHT - 1 };
CHAR_INFO consoleBuffer[WIDTH][HEIGHT];
HANDLE wHnd = GetStdHandle(-11);
HANDLE rHnd = GetStdHandle(-10);
DWORD numEventsRead = 0;
DWORD numEvents = 0;
INPUT_RECORD *eventBuffer = {0};
int wait = 45;
int startGrid[WIDTH][HEIGHT] = { 0 };
int knownGrid[WIDTH][HEIGHT] = { 0 };
int arrowPos[2] = {0,0};
int bomb[2] = {0};
struct xorshift_state seed = {argc == 2 ? (int) argv[1] : 1};
for (int i = 0; i < BOMBS; i++)
{
while (startGrid[bomb[0]][bomb[1]] < -1 || bomb[0] <= 0 || bomb[1] <= 0 || bomb[0] >= WIDTH-1 || bomb[1] >= HEIGHT-1)
{
bomb[0] = (xorshift(&seed) % WIDTH-1) + 1;
bomb[1] = (xorshift(&seed) % HEIGHT-1) + 1;
}
startGrid[bomb[0]][bomb[1]] = -9;
startGrid[bomb[0] + 1][bomb[1] + 1]++;
startGrid[bomb[0] + 1][bomb[1]]++;
startGrid[bomb[0]][bomb[1] + 1]++;
startGrid[bomb[0] - 1][bomb[1] + 1]++;
startGrid[bomb[0]][bomb[1] - 1]++;
startGrid[bomb[0] + 1][bomb[1] - 1]++;
startGrid[bomb[0] - 1][bomb[1] - 1]++;
startGrid[bomb[0] - 1][bomb[1]]++;
}
while(1)
{
if (arrowPos[0] > WIDTH-1) arrowPos[0] = WIDTH-1;
if (arrowPos[0] < 0) arrowPos[0] = 0;
if (arrowPos[1] > HEIGHT-1) arrowPos[1] = HEIGHT-1;
if (arrowPos[1] < 0) arrowPos[1] = 0;
for (int x = 0; x < WIDTH; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
if (knownGrid[x][y] == 1)
{
if (startGrid[x][y] > 0)
{
consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
consoleBuffer[x][y].Attributes = 10;
}
else
{
consoleBuffer[x][y].Char.AsciiChar = 'o';
consoleBuffer[x][y].Attributes = startGrid[x][y] < 0 ? 4 : 17;
}
}
else
{
consoleBuffer[x][y].Char.AsciiChar = 00;
consoleBuffer[x][y].Attributes = 0;
}
if(arrowPos[0] == x && arrowPos[1] == y)
{
consoleBuffer[x][y].Attributes = 112;
}
}
}
WriteConsoleOutput(wHnd,*consoleBuffer,characterBufferSize,characterPosition,&consoleWriteArea);
numEvents = 0;
numEventsRead = 0;
GetNumberOfConsoleInputEvents(rHnd,&numEvents);
if (numEvents)
{
eventBuffer = malloc(sizeof(INPUT_RECORD) * numEvents);
ReadConsoleInput(rHnd,eventBuffer,numEvents,&numEventsRead);
}
if(numEventsRead && wait <= 0)
{
wait = 45;
switch (eventBuffer[0].Event.KeyEvent.wVirtualKeyCode)
{
case 38:
arrowPos[0]--;
break;
case 40:
arrowPos[0]++;
break;
case 37:
arrowPos[1]--;
break;
case 39:
arrowPos[1]++;
break;
case 13:
ExpandGrid(startGrid,arrowPos);
break;
}
}
wait--;
}
}
如果我打开-nodefaultlibs
,这就是我得到的错误字符串:
-------------- Build: Release in Minesweeper2 (compiler: GNU GCC Compiler)---------------
gcc.exe -Wall -Os -ffunction-sections -fdata-sections -c C:\Users\mlfre\OneDrive\Desktop\Minesweeper2\main.c -o obj\Release\main.o
gcc.exe -o bin\Release\Minesweeper2.exe obj\Release\main.o -s -Wl,--gc-sections -nodefaultlibs -lKernel32 -lgcc -lmsvcrt
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x13c): undefined reference to `fesetenv'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1a5): undefined reference to `__dyn_tls_init_callback'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1d9): undefined reference to `__cpu_features_init'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1de): undefined reference to `_CRT_fenv'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1e6): undefined reference to `fesetenv'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1eb): undefined reference to `_setargv'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1f0): undefined reference to `_CRT_fmode'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x206): undefined reference to `_pei386_runtime_relocator'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x25d): undefined reference to `_CRT_fmode'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x271): undefined reference to `_CRT_fmode'
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x2a4): undefined reference to `_CRT_glob'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s),0 second(s))
12 error(s),0 warning(s) (0 minute(s),0 second(s))
所以现在我想知道a)我该如何解决此nodefaultlibs错误,或者b)我还能做些我可能会忽略的减小程序大小的事情吗?
解决方法
尝试使用“编程”技巧来改进程序。比尔·盖茨实际上在他年轻的时候是一个非常好的程序员,请阅读他的一些编程示例。
使用较小的数据类型,例如,使用char代替int(在可能的情况下),或使用int16代替int32。
删除冗余数据,例如:
#define WIDTH 100
#define HEIGHT 100
仅用于:
#define DIMENSION 100
请勿使用struct
。
如果可能,不要使用缓冲区。
请勿使用int argc,char *argv[]
。
仅将键盘用作输入设备。
请勿使用此类数组:
int neighbors[8][2] = {{0,1},{1,0},{0,-1},{-1,-1}};
改用布尔表:int32 neighbors = 0b 0001 0100 0101 0011 1100 1111 1101 0111(此布尔表仅需要32位内存,其中您的阵列需要8 x 2 x 32位= 512位,一半Kbit;-))
使用最有效的最小化设置(即6KB程序版本)编译程序。使用反汇编程序和十六进制编辑器打开已编译的程序,并删除所有不需要的东西,例如纯文本和其他开销等。请注意,这是很多工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。