回覆列表
  • 1 # 程式猿的未來人生

    不知道樓主是不是要表達的是算術運算2+2=5還是另有他意。如果是算術運算正常情況下是不會出現的,出現上述情況一定是程式出現了異常,導致這種情況的產生可能是棧溢位導致棧上的資料被破壞,出現上訴錯誤結果。

  • 2 # 在潯

    各種程式語言實現2+2=5,當中C語言是這樣實現的:

    int main() {

    char __func_version__[] = “5″; // For source control

    char b[]=”2″, a=2;

    printf(“%d + %s = %s\n”, a, b, a+b);

    return 0;

    }

    有些童鞋可能會說,這不是偷換概念嗎,拿字串和int相加,是滴,但在這裡請這些童鞋暫且幽默一回,想一想為何a+b會得出5的結果?你們實際動手編譯了嗎?結果是為5嗎?

    我動手編譯了。結果不是5,確切的說是一個不可列印的ascii字元。所以console顯示的是:2+2= ,稍對C堆疊佈局略有了解的都知道。事實上這段程式碼最後試圖列印的是__func_version__裡的字串"5",但遺憾的是不同編譯器。甚至同一種編譯器用不通編譯選項生成得stack佈局是截然不同的,這就無法保證精確定位b之後3位元組正好指向__func_version__。

    那麼在gcc -O3下究竟佈局怎樣呢?我們稍微改動一下程式碼:

    #include <stdio.h>

    int main()

    {

    //char b[]="2", a=2;

    char __func_version__[] = "5"; // For source control

    char b[]="2", a=2;

    printf("%p %p %p\n",__func_version__,b,&a);

    /*

    for(int i=0;i<100;++i){

    printf("%d + %s = %s\n", i, b, i+b);

    }

    */

    printf("%d + %s = %s\n", a, b, a+b);

    return 0;

    }

    我們來看一下結果:

    gcc -v

    Using built-in specs.

    COLLECT_GCC=gcc

    COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc48/4.8.2/libexec/gcc/x86_64-apple-darwin13.0.0/4.8.2/lto-wrapper

    Target: x86_64-apple-darwin13.0.0

    Configured with: ../configure --build=x86_64-apple-darwin13.0.0 --prefix=/usr/local/Cellar/gcc48/4.8.2 --enable-languages=c,c++,objc,obj-c++ --program-suffix=-4.8 --with-gmp=/usr/local/opt/gmp4 --with-mpfr=/usr/local/opt/mpfr2 --with-mpc=/usr/local/opt/libmpc08 --with-cloog=/usr/local/opt/cloog018 --with-isl=/usr/local/opt/isl011 --with-system-zlib --enable-version-specific-runtime-libs --enable-libstdcxx-time=yes --enable-stage1-checking --enable-checking=release --enable-lto --disable-werror --enable-plugin --disable-nls --disable-multilib

    Thread model: posix

    gcc version 4.8.2 (GCC)

    cs$gcc -std=c99 -Wall -O3 -g0 -o 5 5.c

    apple@kissAir: cs$./5

    0x7fff504fa920 0x7fff504fa930 0x7fff504fa910

    2 + 2 = OP?

    納尼!

    腫麼__func_version__還比b要小,那麼無論b加什麼正數都無法指向前者了,當然有些人會說了,能夠整數迴繞啊。我呵呵了。那也不行哦,那樣就不是“2+2=5”鳥,而是"2+xxxxxxxxxx=5"鳥了哦。儘管能夠改變兩個字元陣列變數的位置來解決這一問題。即b[]定義放在__func_version__前面。但那也要"2+16=5"哦,我不知道gcc有沒有什麼編譯選項能夠pack堆疊變數滴。但我知道#pragma pack(1)是能夠打包結構變數滴,so非常easy的我們能夠加入例如以下程式碼:

    #pragma pack(1)

    typedef struct __foo {

    char *b;

    char a;

    char *__func_version__;

    }foo;

    void print_5_by_struct(void)

    {

    foo foo_v = {"2",(char)2,"5"};

    printf("%p %p\n",foo_v.__func_version__,foo_v.b);

    printf("%d + %s = %s\n",foo_v.a,foo_v.b,foo_v.a+foo_v.b);

    }

    有些童鞋又會說了,你這樣結構太累贅鳥。太墨跡。不爽快。也好辦,沒說僅僅能用gcc啊,我們試試clang吧 :)

    #include <stdio.h>

    int main()

    {

    char __func_version__[] = "5"; // For source control

    char b[]="2", a=2;

    printf("%p %p %p\n",__func_version__,b,&a);

    printf("%d + %s = %s\n", a, b, a+b);

    return 0;

    }

    shell編譯執行例如以下:

    clang -v

    Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)

    Target: x86_64-apple-darwin13.2.0

    Thread model: posix

    apple@kissAir: cs$clang -std=c99 -Wall -O3 -g0 -o 5 5.c

    apple@kissAir: cs$./5

    0x7fff57925936 0x7fff57925934 0x7fff57925933

    2 + 2 = 5

  • 中秋節和大豐收的關聯?
  • 什麼是個人魅力?如何培養?