《深入理解計算機系統》
objdump -s -d <程序> : 可以看到在內存中的段等信息
內存佈局:
由高到低:
1.內核空間
2.stack
3.share lib
4.heap
5.rw
6.ro
7.保留區reservation
/*************************************************************************
> File Name: class.c
> Author: khalil
> Mail: [email protected]
> 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