【2015/10/18】C學習日誌_Day8 數據類型及其位表示,指針,內存狀態

D8:
    《深入理解計算機系統》
    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


發佈了28 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章