Why is "2 + 2 = 5" in C?

Source: Internet
Author: User

I wrote this original article because I saw an article by geeks titled interesting programming languages implementing 2 + 2 = 5, where C is implemented in this way:

int main() {char __func_version__[] = “5″; // For source controlchar b[]=”2″, a=2;printf(“%d + %s = %s\n”, a, b, a+b);return 0;}

Some children's shoes may say that this is not a concept of stealing and replacing them with strings and int. But here, please make these shoes humorous for the moment, think about why a + B will produce 5 results? Have you actually compiled it? Is the result 5?

I compiled it by hand. The result is not 5. It is definitely an printable ascii character. Therefore, the console displays 2 + 2 =. I know a little about the C STACK layout, in fact, this Code finally tries to print the "5" string in _ func_version _, but unfortunately different compilers, even the stack layout generated by the same compiler without the compilation option is completely different, which cannot ensure that the precise positioning of the 3 bytes after B exactly points to _ func_version __.

So what is the layout under gcc-O3? Let's slightly modify the code:

#include 
 
  int main() {//char b[]="2", a=2;char __func_version__[] = "5"; // For source controlchar 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;}
 

Let's take a look at the results:

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 :.. /configure -- build = x86_64-apple-darwin13.0.0 -- prefix =/usr/local/Cellar/gcc48/4.8.2 -- enable-languages ages = c, c ++, objc, obj-c ++ -- program-suffix =-4.8 -- with-gmp =/usr/local/opt/gmp4 -- with-mpfr =/usr/local/opt/mpfr2 -- -mpc =/usr/local/opt/libmpc08 -- with-cloog =/usr/local/opt/cloog018 -- with-isl =/usr/local/opt/isl011 --- 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?


Nana! Swollen _ func_version _ is smaller than B, so no matter what positive number B adds, it cannot point to the former. Of course some people will say, it can be an integer round back, I am sorry. That's not the case. It's not the "2 + 2 = 5" bird, but the "2 + xxxxxxxxxx = 5" bird. Although the location of two character array variables can be changed to solve this problem, that is, B [] is defined before _ func_version, but it also requires "2 + 16 = 5". I don't know if gcc has any compilation options to pack the stack variable drops, But I know # pragma pack (1) we can package the structure variable drops. so we can simply add the following code:

#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);}

In the end, "2 + 2 = 5" is printed as expected ", If you have other children's shoes that know how to pack variables, please let me know. Thank you.

Some children's shoes will say again, you are too cumbersome, too ink, not happy! Well, we didn't say we could only use gcc. Let's try clang :)

#include 
 
  int main() {char __func_version__[] = "5"; // For source controlchar 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 compilation and running are as follows:

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


Therefore, I am not sure whether I want to learn C. I want to learn how to use it. Thank you for your attention.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.