首页 > 代码库 > C语言与内存模型初探

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("\n");    }    else    {        printf("Not match!\n");    }    printf("a = %u\n",a);    printf("a = %d\n",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 码字符
十进位十六进位 十进位十六进位 十进位十六进位 十进位十六进位
03220  056388 08050P 10468h
03321! 057399 08151Q 10569i
03422" 0583A: 08252R 1066Aj
03523# 0593B; 08353S 1076Bk
03624$ 0603C< 08454T 1086Cl
03725% 0613D= 08555U 1096Dm
03826& 0623E> 08656V 1106En
03927 0633F? 08757W 1116Fo
04028( 06440@ 08858X 11270p
04129) 06541A 08959Y 11371q
0422A* 06642B 0905AZ 11472r
0432B+ 06743C 0915B[ 11573s
0442C, 06844D 0925C\ 11674t
0452D- 06945E 0935D] 11775u
0462E. 07046F 0945E^ 11876v
0472F/ 07147G 0955F_ 11977w
048300 07248H 09660` 12078x
049311 07349I 09761a 12179y
050322 0744AJ 09862b 1227Az
051333 0754BK 09963c 1237B{
052344 0764CL 10064d 1247C|
053355 0774DM 10165e 1257D}
054366 0784EN 10266f 1267E~
055377 0794FO 10367g 1277FDEL
 
 
【注】小端模式
所谓的小端模式(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是不是这样做的。

C语言与内存模型初探