D8:
《深入理解计算机系统》
objdump -s -d <程序> : 可以看到在内存中的段等信息
内存布局:
由高到低:
1.内核空间
2.stack
3.share lib
4.heap
5.rw
6.ro
7.保留区reservation
《深入理解计算机系统》
objdump -s -d <程序> : 可以看到在内存中的段等信息
内存布局:
由高到低:
1.内核空间
2.stack
3.share lib
4.heap
5.rw
6.ro
7.保留区reservation
/*************************************************************************
> File Name: class.c
> Author: khalil
> Mail: hsgwpj@gmail.com
> Created Time: Sun 18 Oct 2015 09:11:28 AM CST
************************************************************************/
#if 0
#include<stdio.h>
int main(int argc ,char ** argv)
{
//定点数
char a = 10 ; //字符 1byte
short b = 20 ; //2 bytes
int c = 30; //4 bytes
long d = 40; //4 bytes 32位操作系统-4 64位-8 (等同于指针大小)
long long int e = 50; //8 byetes
//有符号数与无符号数
signed int aa = 10 ;
//其位表示为
//eg:000000000 00000000 00000000 00001010
//
// 对于正数:原码和补码相等
//
// 对于负数:
// -1 = 1000 0001 (原码: 人对于负数的认识)
//
//* 计算机只识别补码
//
// - x = 0 - x = 0000 0000 - x(向上借位)
//
//* 负数(原码)除符号位外,其他位按位取反,末位加1
//
// -1 = 1000 0001 = 1111 1110 = 1111 1111
// 0 - x = x(反) + 1
//
//无符号数:
//
// unsigned char a ; ( 0 - 255 )
// char b ; ( -128 - 127)
//
// unisigned char c = 0;
// c-- = 255 ;
//
// size_t == unsigned int
//浮点数
float f = 12.25; //4 bytes
double g = 2.5; //8 bytes
printf("size of char :\t %d\n",sizeof(a));
printf("size of short :\t %d\n",sizeof(b));
printf("size of int:\t %d\n",sizeof(c));
printf("size of long :\t %d\n",sizeof(d));
printf("size of long long int :\t %d\n",sizeof(e));
printf("size of float :\t %d\n",sizeof(f));
printf("size of double :\t %d\n",sizeof(g));
return 0 ;
}
#endif
#if 0
#include<stdio.h>
#include<string.h>
int comp_len(const char *str1,const char *str2);
int comp_len(const char *str1,const char *str2)
{
//return strlen(str1) - strlen(str2) > 0 ; // wrong ver
// size_t strlen(const char *s); 返回值是一个无符号类型!
return strlen(str1) > strlen(str2);
// size_t - size_t
// 《深入理解计算机系统》
}
int main(int argc , char ** argv)
{
char *str1 = "wafawf";
char *str2 = "afiuwabfiawfbiawf";
comp_len(str1,str2);
return 0;
}
#endif
#if 0
#include<stdio.h>
int main(int argc , char ** argv)
{
float a = 12.25;
//浮点数的位存储形式:
//
// 12.25 => 1100.01(二进制) = 1.10001 * 2^3 (二进制科学技术法)
// 2*3+ 2*2 + 2^-2
//
// 3 -> 指数位
// 10001 -> 尾数
// 0 -> 符号位
//规则如下:
// 12.25:
// 0 0000001 |1
// 1111111 |1
// 0 1000001 |0 100001 00 |00000000 |00000000
// f zzzzzzz |z wwwwww ---|----补零-|--------
// f符号位 z指数位 w尾数位
// (1)左1位符号位,正数0,负数1
// (2)指数位占8位 如果是正数 需要加127
// (3)尾数位32-1-8=23位
//
// 精度: 尾数位 : 2^23约等于7位
//
// 大端机器:数值上的高位放在内存上的低位 (服务器)
//
// 小端机器:........高..............高.. (PC)
//
//* 通过对位表示的理解 将浮点数转化为整形数
double b = 233.333;
//double 的位表示:
//(1)符号位 -> 1
//(2)指数位 -> 11
//(3) 尾数位 -> 52
//
//2^52 约等于15,16位
return 0;
}
#endif
#if 0
#include<stdio.h>
#include<stdlib.h>
int main(int argc ,char ** argv)
{
int a = 10;
// int * p = (int *)malloc(sizeof(int));
// int ** q = (int **)malloc(sizeof(int **));
// p = &a;
// q = &p;
int *q = &a;
int **p = &q;
//void s; 变量进行定义的时候一定要告诉编译器变量的大小
void * m; //指针类型的大小是固定的
//void * 可以接受任意类型的指针,它是泛型编程的基础
//
//1.指针是一个变量,它在内存中也有地址
//2.指针的功能是记录地址
//3.指针具有类型限定(指类)
//
//指针的大小: 32位下 4bytes
// 64位下 8bytes
// * 与long类型同步!
printf("%d",**q);
return 0;
}
#endif
#if 0
#include<stdio.h>
int main(int argc , char ** argv)
{
char *str1 = "hello,world!";
char str2[] = "hello,world!";
// char str3[100] = "hello,world!";
char str3[6] = {0};
//第一个不能修改字符串的字符 在内存的常量区
//第二三个可以修改 在栈中的开辟空间中由下而上存储
//
//str1为指针(栈上),指向常量区的一个字符串,该字符串不可修改
//str2,str3为字符数组,在栈上
//练习:通过直接更改 str3[*] = ‘'l' 将str2改为hlllo
//
int i;
printf("before:%s\n",str2);
printf("str 1 地址: %p\n",str1);
printf("str 2 地址: %p\n",str2);
printf("str 3 地址: %p\n",str3);
for (i = 0 ; i < 30 ; i++)
{
printf("This is %d : %c\n",i,str3[i]);
}
str3[17] = 'l';
//内存对齐的缘故!
printf("after :%s\n",str2);
return 0;
}
#endif
#if 0
#include<stdio.h>
//使用方法: 对位置进行标记
//
//如果进行部分初始化,未初始化的值从已经初始化的值开始向后加一,如果第一个
//元素都没有初始化,则从0开始
//
enum flag{
INDEX1,
INDEX2,
INDEX3 = 10,
INDEX4,
INDEX5 = 21,
INDEX6
};
int main(int argc , char ** argv)
{
enum flag a ;
//枚举类型的大小是4字节(和int相同)
printf("%d\n",sizeof (a));
return 0;
}
#endif
#if 0
#include<stdio.h>
int b = 10 ; //定义式
//extern int b ; //外部声明!
extern void function(); //从其他.c查找是否有外部函数声明!
//
int main(int argc , char ** argv)
{
int a = 10 ; //这称为定义:即分配内存,由告诉内存的标记
int b,c; //wrong ver. 同时要注意变量一定要进行初始化
//
//习惯:
//
//1.变量定义一定要初始化 尤其是指针;
// eg. 定点数初始化为0,浮点数初始化为0.0,指针初始化为NULL,
// 数组初始化为0(char类型为{0});
//2.每一行只做一个操作;
//3.不允许隐式声明,所有变量必须是显式声明;
//
//
function();
return 0;
}
#endif
#if 0
#include<stdio.h>
#define P_CHAR char * //定义类型的时候不能加括号!
typedef int *p_int;
#define TRUE (1)
#define FALSE (0)
typedef unsigned char Boolean ; //0-255 True 1 / False 0
//类型重定义,例如布尔类型的定义
int main(int argc , char ** argv )
{
P_CHAR a,b; // == char* a,b ; == char *a , b;
p_int c,d; // == int * c ; int * d;
Boolean ok =FALSE;
printf("%d",ok);
return 0 ;
}
#endif
#if 0
#include<stdio.h>
int main (int argc , char ** argv)
{
int a = 10 ;
const int b = 20; //const修饰变量代表是 常变量 在内存中占有空尽阿
//常变量是可以被修改的!
9; //常量 常量在内存中没有空间
int const c = 20; //他们是一样的
const int *p = &a; //p指向的对象的值不可引用*p更改
int const *q = &a; //
int * const m = &a; //int * m 所指向的地址不可改变
const int * const n = &a; //上述两个都不能改
//修改常变量:(可以通过指针来修改) - 然而最好不要改 这是编译器的漏洞
int *y = (int *) &b; //如果没有 (int *) 进行强制转换 会有warning
*y = 200;
printf("%d",*y);
return 0 ;
}
#endif
#if 0
#include<stdio.h>
int a ; //声明式 如果没有这一步 func1() 报错(找不到a)
void func1(void);
void func1(void)
{
printf("a = %d\n",a);
}
int a = 10; //定义式
int main(int argc , char ** argv )
{
int a = 20;
{
int a = 10;
a++;
printf("a = %d\n",a);
}
printf("a = %d\n",a);
func1();
return 0 ;
}
#endif
#if 0
#include<stdio.h>
#include<stdlib.h>
//下面列出我们可以操作的内存
#define SIZE (10)
int global_value = 10; //全局区
static int static_value = 20; //静态区
int * func1(void);
int * func1(void)
{
//自动变量:
//
//函数调用时定义,函数结束时回收
int a = 10;
int array[] = {12,23,45,67};
int i =0;
for ( ; i < (sizeof(array) / sizeof(array[0])) ; ++i)
{
printf("%d\n",array[i]);
}
a++;
return array; //自动变量array在func1()结束后会被回收 这样会warning
}
int main(int argc , char ** argv)
{
int a = 10; //stack
int *p_int = (int * )malloc(sizeof(int)*SIZE); //p_int 在stack上
//而malloc申请的空间在heap上
if (p_int == NULL){
fprintf(stderr,"the memory is full! \n");
exit(1);
}
p_int[0] = 1;
free(p_int);
func1();
return 0;
}
#endif
#if 1
//作业1:escape() unescape()
#include<stdio.h>
#include<stdlib.h>
char * escape ( char *dest , char *src);
char * unescape ( char *dest , char *src);
int main(int argc , char ** argv)
{
char * str1 = "hello\n,world\t\neveryone!";
char * str2 = "233";
printf("样本:\n%s\n\n",str1);
printf("defore:\n%s\n\n",str2);
str2 = escape(str2,str1);
printf("escape:\n%s\n\n",str2);
str2 = unescape(str2,str2);
printf("unescapde:\n%s\n\n",str2);
return 0 ;
}
char * escape ( char *dest_str , char *src_str)
{
char *dest = (char * )malloc(sizeof(dest_str));
char *result = dest;
char *src = src_str;
char ch = '\0';
if ( dest_str == NULL || src_str == NULL )
{
return dest_str;
}
// while(( *dest++ = *src++ ) != '\0')
while( *src != '\0')
{
ch = *src ;
switch(ch)
{
case('\t'): *dest++ = '\\';
*dest++ = 't';
break;
case('\n'): *dest++ = '\\';
*dest++ = 'n';
break;
default:
*dest++ = ch;
break;
}
src ++ ;
}
*dest = '\0';
return result;
}
char * unescape ( char *dest_str , char *src_str)
{
char *dest = (char * )malloc(sizeof(dest_str));
char *result = dest;
char *src = src_str;
char *ch_next ='\0';
char ch = '\0';
if ( dest_str == NULL || src_str == NULL )
{
return dest_str;
}
// while(( *dest++ = *src++ ) != '\0')
while( *src != '\0')
{
ch = *src ;
ch_next = src+1;
switch(ch)
{
case('\\'):
if(*ch_next == 'n')
{
*dest++ = '\n';
src++;
}
else if(*ch_next == 't')
{
*dest++ = '\t';
src++;
}
break;
default:
*dest++ = ch;
break;
}
src++ ;
}
*dest = '\0';
return result;
}
#endif
#if 0
#include<stdio.h>
int main(int argc , char ** argv)
{
int i = 0;
int j = 0;
for ( ; i < 1000000 ; i++ )
{
for( j = 0 ; j < i ; j++ )
{
if( i % j == 0)
{
print("%d\n",i);
break;
}
}
}
}
#endif