• C语言与内存模型初探



    #include<stdio.h> #include<string.h> int main(){ long long int a = 2<<30; char string[] = "Hello China1!"; char string2[] = "Hello China2!"; if(0==strcmp(string,string2)) { printf(string); printf(" "); } else { printf("Not match! "); } printf("a = %u ",a); printf("a = %d ",a); char c[] = {'I',' ','a','m',' ','l','i','u','k','u','n'}; printf(c); return 0; }

      

     
     
    C语言字符串不加结束符,打印出的结果不好预测。这应该跟操作系统的内存模型有关,理由如下:
    Windows GCC编译打印结果是:
    Not match!
    a = 2147483648
    a = -2147483648
    I am liukunHello China2!
     
    Linux GCC编译打印结果是:

    Not match!
    a = 2147483648
    a = -2147483648
    I am liukunliukun

    我也不知道为什么 Hello China2 内存上跟 I am liukun 连在一起的。
    反汇编出来的代码好乱也不好读。
     
    ASCII 码表:
    ASCII 码 字符   ASCII 码 字符   ASCII 码 字符   ASCII 码 字符
    十进位 十六进位   十进位 十六进位   十进位 十六进位   十进位 十六进位
    032 20     056 38 8   080 50 P   104 68 h
    033 21 !   057 39 9   081 51 Q   105 69 i
    034 22 "   058 3A :   082 52 R   106 6A j
    035 23 #   059 3B ;   083 53 S   107 6B k
    036 24 $   060 3C <   084 54 T   108 6C l
    037 25 %   061 3D =   085 55 U   109 6D m
    038 26 &   062 3E >   086 56 V   110 6E n
    039 27 '   063 3F ?   087 57 W   111 6F o
    040 28 (   064 40 @   088 58 X   112 70 p
    041 29 )   065 41 A   089 59 Y   113 71 q
    042 2A *   066 42 B   090 5A Z   114 72 r
    043 2B +   067 43 C   091 5B [   115 73 s
    044 2C ,   068 44 D   092 5C   116 74 t
    045 2D -   069 45 E   093 5D ]   117 75 u
    046 2E .   070 46 F   094 5E ^   118 76 v
    047 2F /   071 47 G   095 5F _   119 77 w
    048 30 0   072 48 H   096 60 `   120 78 x
    049 31 1   073 49 I   097 61 a   121 79 y
    050 32 2   074 4A J   098 62 b   122 7A z
    051 33 3   075 4B K   099 63 c   123 7B {
    052 34 4   076 4C L   100 64 d   124 7C |
    053 35 5   077 4D M   101 65 e   125 7D }
    054 36 6   078 4E N   102 66 f   126 7E ~
    055 37 7   079 4F O   103 67 g   127 7F DEL
     
     
    【注】小端模式
    所谓的小端模式(Little-endian),是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。
    例子:
    0000430: e684 6c4e 0100 1800 53ef 0100 0100 0000
    0000440: b484 6c4e 004e ed00 0000 0000 0100 0000
    在小端模式下,前32位应该这样读: 4e 6c 84 e6( 假设int占4个字节)
    记忆方法: 地址的增长顺序与值的增长顺序相同
     
    > objdump -d datatype.exe > output.txt
     
    反汇编代码节选:
    ;I am liukun 的地址安排
    4014e2: c6 44 24 11 49 movb $0x49,0x11(%esp)
    4014e7: c6 44 24 12 20 movb $0x20,0x12(%esp)
    4014ec: c6 44 24 13 61 movb $0x61,0x13(%esp)
    4014f1: c6 44 24 14 6d movb $0x6d,0x14(%esp)
    4014f6: c6 44 24 15 20 movb $0x20,0x15(%esp)
    4014fb: c6 44 24 16 6c movb $0x6c,0x16(%esp)
    401500: c6 44 24 17 69 movb $0x69,0x17(%esp)
    401505: c6 44 24 18 75 movb $0x75,0x18(%esp)
    40150a: c6 44 24 19 6b movb $0x6b,0x19(%esp)
    40150f: c6 44 24 1a 75 movb $0x75,0x1a(%esp)
    401514: c6 44 24 1b 6e movb $0x6e,0x1b(%esp)
    .......
    40144d: c7 44 24 1c 48 65 6c movl $0x6c6c6548,0x1c(%esp)
     
    End
    总之,使用C编程时还是要多注意,操纵内存虽然爽,但是一不小心就会埋下Bug。
    话说两个没有使用到的局部变量字串应该可以被编译器优化的,如果是这样的话栈里面就不会为其分配内存啦,不知道Linux下面的GCC是不是这样做的。
     
  • 相关阅读:
    HashMap的put方法
    死锁相关
    AVL树
    xss漏洞
    hash
    古典密码学教学
    python | 实现控制多台机器的脚本
    python | 端口扫描器(多线程)
    每日一洞 | 细说渗透江湖之出荆棘入深林
    每日一洞 | 细说渗透江湖之柳暗花明又一村
  • 原文地址:https://www.cnblogs.com/learn-to-rock/p/5874524.html
Copyright © 2020-2023  润新知