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 码 字符
十进位 十六进位   十进位 十六进位   十进位 十六进位   十进位 十六进位
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是不是这样做的。

时间: 2024-08-10 02:09:28

C语言与内存模型初探的相关文章

c语言内存模型

文章一.C语言的内存分配模型 1.程序代码区:存放函数体的二进制代码. 2.全局区数据区:全局数据区划分为三个区域.全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域.常量数据存放在另一个区域里.这些数据在程序结束后由系统释放.我们所说的BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称. 3.栈区:由编译器自动

C语言内存模型 (C memory layout)

 一. 内存模型                                                                         1. .text 代码区(code section).由编译器链接器生成的可执行指令,程序执行时由加载器(loader)从可执行文件拷贝到内存中.为了安全考虑,防止别的区域更改代码区数据(即可执行指令),代码区具有只读属性.另一个方面,代码区通常具有可共享性(sharable),即在内存中只有一份代码区,如编译器,假如同时有多个编译任务

C语言 二级指针内存模型

//二级指针第一种内存模型 #include<stdio.h> #include<stdlib.h> //说明:①:类似于int a[5]={0},数组名a是一维数组a中首元素的指针:(我自认为此假设可应用于多维数组与指针) //②二级指针的主要功能是修改一级指针的值 //打印一维数组 int PrintArr(char **pin,int num){ int ERRO_MSG = 0; if (pin==NULL) { ERRO_MSG = 1; printf("pin

C语言 二级指针内存模型混合实战

//二级指针内存模型混合实战 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> //将内存模型①和内存模型②的数据拷贝到内存模型③ char ** threemodel(char **pin1,int num1,char (*pin2)[20],int num2,char **pin3,int *pnum3){ if (pin1==NULL

C语言 二级指针内存模型③

//二级指针内存模型③ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> //内存模型详解 //一维数组类型是 typedef int Myarr[5]; Myarr a;(其中Myarr是一维数组类型) //Myarr *p;p是一维数组的指针 //是一维数组的指针的类型是 typedef int(*PArrType)[5]; PArrT

c语言二级指针内存模型

第一种: 指针数组作为输入参数 char *myArray[] = {"aaaaaa", "ccccc", "bbbbbb", "111111"};//指针数组,数组中的每个元素都是指针,int num = 4; void printMyArray11(char **myArray, int num) { int i = 0; for (i=0; i<num; i++) { //printf("%s \n&qu

JVM内存模型理解

Java虚拟机(Java VirtualMachine 简称JVM)是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java 最具吸引力的特性之一. JVM内存模型 1.方法区和堆是所有线程共享的数据区 1)堆:存放对象的实例 2)方法区:存放已被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码 3)运行时常量池:是方法区的一部分,存放Class的版本.字段.方法.接口等描述信息,字符串池就是这个!!! 2.程序计数器.虚拟机栈.本地方法栈是线程隔离的数据区 4)程序

【转】深入理解JVM—JVM内存模型

http://www.cnblogs.com/dingyingsi/p/3760447.html#3497199 我们知道,计算机CPU和内存的交互是最频繁的,内存是我们的高速缓存区,用户磁盘和CPU的交互,而CPU运转速度越来越快,磁盘远远跟不上CPU的读写速度,才设计了内存,用户缓冲用户IO等待导致CPU的等待成本,但是随着CPU的发展,内存的读写速度也远远跟不上CPU的读写速度,因此,为了解决这一纠纷,CPU厂商在每颗CPU上加入了高速缓存,用来缓解这种症状,因此,现在CPU同内存交互就变

深入理解Java内存模型(1 ) -- 基础(转载)

原文地址:http://www.infoq.com/cn/articles/java-memory-model-1 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递. 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.在消息传递的并发模型里,线程之间没有公共状态,线