C++语言学习

C学习

程序:
高并发 低耦合 多线程 
/**#include <stdio.h>
int main()
{
printf("hello world \n"); 
return 0; 
}

#include <stdio.h>
int main()
{
	printf("hello world!")
	return 0;
}


    printf("dadawdada5d\n\
		dadawdadwadwad\n\		第一个/配合N使用 第二个使程序认为上行是下行的延续 
		")
	
	
C语言的输出格式
%s字符串
%c字符
%d有符号的十进制数
%u无符号的十进制数
%p指针
%% %
%a 浮点数 
		
_Bool 布尔类型
整数类型:  short int / int / long int / long long int 
浮点数类型: float / double / long double
字符类型: char
布尔类型: _Bool
枚举类型: enum


sizeof运算符
sizeof 运算符用于获取数据类型或表达式长度
-sizeof(object); //sizeof(对象)
-sizeof(type_name);//sizeof(类型)
-sizeof object; //sizeof 对象

signed 和 unsigned
存放负数 and 负数和0 
 

signed short int
unsigned short int 
signed int
unsigned int
signed long int
unsigned long int 
signed long long int 
unsigned long long int 

bit b cpu能读懂的数据
内存机构中最小的单位
1byte = 8bit
1byte = 1111 1111 = 255 (FF)

pow算数函数 
pow (2,32) 2的32次方 




#include <stdio.h>
int main()
{
	int result = pow(2,32) - 1 ; 
	printf("result = %d\n" , result); 
	return 0;; 
} 

char name[5]  声明字符串  且  字符串个数为5

name[0] = "D"; 
name[1] = "o"; 
name[2] = "n"; 
name[3] = "g"; 
name[4] = "Z";
e31 +3L 
\l  
char name[5] = {'D','o','n','g','Z'};

C语言的字符串 就是 字符数组 
索引号从0开始 

运算符
赋值运算符
方括号运算符
算数运算符 + - * / 

1 + 2 
操作数 + 运算符 + 操作数 双目运算符
+1 单目运算符

表达式 1 + 1  'a' + 'b' a + b  



C语言的优先级和选择性

复合的赋值运算符
a = a + 1  -> a +=1
a = a - 1  -> a -=1
a = a * 1  -> a *=1
a = a / 1  -> a /=1
a = a % 1  -> a %=1 

自增自减运算符
a++
++a
a--
--a

逗号运算符
a,b,c,d,e,f 


强制转化类型
int a;
(double)a (flode)a (long)a
 

初始化数组 
int a[10] = {0} 
int a[10] = {1,2,3,4,5,6,7,8,9}
int a[10] = {1,2,3,4}		剩下的被系统初始化为0 

指定初始化元素
int a[10] = {[3]=3 , [5]=5 ,[7]=7}


定义数组的结束符 '\0'

字符串处理函数

 
#include <string.h>
strlen 获取字符串的长度
strcpy strncpy拷贝字符串

strcpy(a,b) 把b的值copy给a
strcpy(c,"Copy Sucess!"); 把copy sucess 的值赋给数组c 
strncpy限制copy字符串的长度
char a[] = "To Be Continues" 
char b[40];
strncpy(a,b,5)	5=限定的字符长度为5 
输出:To Be	=	5byte 

strcat 	strncat连接字符串 
strucat限制连接字符串的字符长度
 
#include <stdio.h>
#include <string.h>
int main()
{
	char str1[]="DongZai ";
	char str2[]="Love's Han";
	//strcat(str1,str2);
	strncat(str1,str2,6);
	printf("str1:%s\n",str1);
}

比较字符串 
strcmp strncmp 

int整形存储变量在内存中占用4个字节 	 char字节型存储变量在内存中占用4个字节

指针和指针变量 
a -> 10001
b -> 10002
c -> 10003
d -> 10004
pa -> 11000
pf -> 11004 

定义指针变量

类型名 *指针类型变量名

char *pa;	//定义一个指向字符型变量的指针变量 
int *pb; 	//定义一个指向整型的指针变量

取地址运算符和取值运算符

如果需要获取某个变量的地址,可以用取地址运算符(&)
char *pa = &a;
int *pb = &f;


如果需要访问指针变量指向的数据,可以使用取值运算符(*);
printf("%c,%d\n",*pa,*pb); 
 

#include <stdio.h> 
int main()
{
	char a = 'C';
	int  b = 123;
	
	char *pa = &a;
	char *pb = &b;
	
	printf("a = %c\n" , *pa);
	printf("b = %d\n" , *pb);
	
	*pa = 'D';
	*pb =124;
	
	printf("now a = %c\n" , *pa);
	printf("now b = %d\n" , *pb);

	printf("sizeof pa = %c\n" , sizeof(pa));
	printf("sizeof pb = %d\n" , sizeof(pb));

	return 0;
}

输出
a = C
b = 123
now a = D
now b = 124
sizeof pa = 8;		//32架构的系统 输出为4		因为32位编译器int类型的4个字节	64位编译器8字节 
sizeof pb = 8;


#include <stdio.h>
int main()
{
	int a;
	int *p = &a;
	
	printf("请输入一个数:");
	scanf("%d",&a);
	printf("a = %d\n",a);
	
	printf("请输入一个数:");
	scanf("%d",p);w
	printf("p = %d\n" ,*p); 


	return 0;
} 

 
对比标准的下标法访问数组元素,这种使用指针进行间访问的方法叫指针法. 

char a[] = {1,2,3,4,5,6,7,8,9};
char *p = a; 
*(p+1) 	这种意义相当于指向距离指针所在位置向前或向后的第n个元素

*p的位置与a[0]的位置相等,在p的基础上进行加减相当于去调用a[]数组中的其他元素 



直接用指针定义字符串  


指针和数组的区别
 
 
 
#include <stdio.h>
int main()
{
        char str[]= "I love Han Han";
        char *target = str;
        int count = 0;

        while(*target++ != '\0')			*target++	优先级 先+++ 后* !=比较  target++指定
											下一个元素得位置 *target调用指针函数 相当于a[target] 
											来指向下一个字符中的内容 接着与'\0'数组结束符号进行判断,如果不是结束符号,那么 
											count+1 继续运行 
        {
        
        	countr ++
                count++;
        }
        printf("togeter have string : %d",count);
        return 0;
}

lvalue rvalue	左值和右值区别

数组名只是一个地址,而指针是一个左值. 

指针数组和数组指针 


int *p1[5];		--------->		指针数组	
int(*p2)[5];	---------> 		数组指针 

指针数组

int *p1[] 		
int * int * int * int * int * 
指针数组是一个数组 每个数组元素存放一个指针变量 

int a = 1
int b = 2
int b = 3
int d = 4
int e = 5
int f = 6

int *p1[$] = {&a,&b,&c,&d,&e.&f}
int i;


指针数组;
指向数组一个特定的数组
		相当于一个指针类型的数组 
int *p[4]=
{
	"",
	"",
	"",
	"",
	""
};

数组指针:
相当于用指针来表示数组中的第一个元素的位置
for (i=0;i<5;i++)
{
	printf("%d\n",*(p+1));
}
指向数组的第一个元素 不是指向数组 
int temp[] = {1,2,3,4,5,6,7,8,9};
int *p2[5]=&temp;





函数:
void func()
{
	.....
} 


void func()
{
	count++;
} 
int count;
int main()
{
	func();
	printf("%d",count)
} 
按照程序执行从上往下的顺序 在函数后面定义变量 一定会报错的
这时可以用到一个函数
extern count
告诉程序这个变量在后面  等等在调用.

 void func()
{
	extern count;
	count++;
} 
int count;
int main()
{
	func();
	printf("%d",count)
} 

这样就不会报错了
 
C语言的作用域
 - 代码块作用域
 - 文件作用域
 - 原型作用域 
 - 函数作用域 

代码块作用域:
从标志该符号块结束的??大括号处结束
 

定义: 当一个变量被定义的时候,编译器为变量中申请内存空间填充一定的值 
声明: 当一个变量被声明的时候,编译器就知道该变量被定义在其他地方 
局部变量即使定义又是声明 

链接属性: 
 

 external	多个文件中声明的同名标识符表示同一个实体 
 internal	单个文件中声明的同名标识符表示同一个实体 
 none		声明的同名标识符被当成独立不同的实体 
 
 只有具备文件作用域的标识符才能拥有external或internal的链接属性,其他作用标识符都是none属性 
 

test.c
#include <stdio.h> 

char *c = "";

void a(void);
void b(void)

int main()
{
	a();
	b();
	
	printf("%s\n",c)
	
	return 0;
}

a.c
extern char *c;
void a(void) 
{
	c = "Niubi";
} 

b.c
extern char *c;
void b(void) 
{
	c = "DongZai";
} 

生存期:
 -静态存储期		只有程序关闭 才会释放 
 -自动存储期		代码块作用域 在代码快结束的时候 就会被释放 
 
 具有文件作用域的变量属性静态存储期,函数也属
 于静态存储期.属于静态存储期的变量在程序执行
 期间将一直占据存储空间,直到程序关闭才释放 
 
  存储类型其实是指变量值的内存类型,C语言提供了5种不同的存储类型 
	 -auto
	 -register
	 -static
	 -extern
 -typedef
  	
 auto自动变量 
 在代码块中声明的变量默认的存储类型就是自动变量,使用关键字auto来描述
 #include <stdio.h>
 int main()
 {
 	auto int i,j,k;
 	return 0;
 }
 #include <stdio.h>
 int i;
 int main()
 { 
 	auto int i;
 	return 0;
 }

 寄存器变量(register) 
 如果将变量声明为寄存器变量,那么你就不能通过取值运算符获取该变量的地址 
 
 
 
 startic 静态局部变量 
 在默认情况下所有的 所有声明的变量为auto类型
 如果用static来声明变量, 是具有静态存储器,与全局变量一致,需要等待程序结束,才会释放 
 

#include <stdio.h>

void func(void);

void func(void)
{
        static int count = 0;
        printf("count : %d\n",count);
        count++;
}


int main()
{
        int i;
        for(i=0;i<10;i++)
        {
                func();
        }
        return 0;
}

count : 0
count : 1
count : 2
count : 3
count : 4
count : 5
count : 6
count : 7
count : 8
count : 9


可以看到结果,说明每一次调用func count是不变的,所以以此+1 一直到9
 要是把static删除,则一直输出0 
count : 0
count : 0
count : 0
count : 0
count : 0
count : 0
count : 0
count : 0
count : 0
count : 0
可以证明:通过定义静态存储器,与全局变量一样是静态存储类型,需要程序结束才能释放 


static 和 extern
static关键字可以将具有external链接属性的标识符转化为internal链接属性,而external关键字是用于告诉编辑器这个变量
或者函数在别的地方以及定义过了,先去别的地方找找,不急着报错 

------------------------------------------------- 
#include <stdio.h>
int count;				可以看到count在这里只是声明没有定义 相当于去external 

void func(void);				

void func()
{
        printf("count = %d\n",count);
}

------------------------------------------------ 
void func();
int count = 521;		这里的count定义了 

int main()
{
        func();
        return 0;
}
                                                                                    
-------------------------------------------------      

auto 和  register 定义的变量具有自动存储期 

startic 和 external 定义的变量具有静态存储期 






递归编程思路 
#include <stdio.h>

void recursion(void);
void recursion(void)
{
        static int count = 10;
        printf("Hello!\n");
        if(count-- != 0){
                recursion();		函数中自己调用自己  加个判断 
        }
}

int main()
{
        recursion();
        return 0;
}
 
 
更灵活的内存管理放式

#include <stdlib.h> 
 
malloc 	申请动态内存空间 

free	释放动态内存空间 

calloc	申请并初始化一些列内存空间 

realloc 重新分配内存空间 

 malloc 
 -void *malloc(size_t size);
 malloc 函数向系统申请分配size个字节得内存空间,并返回一个指向这块空间的指针.
 如果函数调用成功,返回一个指向申请得内存空间得指针,由于返回类型是void指针(*void),所以它可以被
 转化成任意类型的数据,如果函数调用失败,返回值是Null.另外,如果size参数设计为0,返回值可能是null
 但这并不意味着函数调用失败. 
 
 #include <stdio.h>
 #include <stdlib.h>
  
  int main()
  {
  	int *p;
  	p =(int *) malloc(sizeof(int));
  	
  	if(p == NULL)
  	{
	 	printf("Error You Don't have many money!!");
		exit(1); 
	}
	
	printf("Please You Enter a number : ")
	scanf("%d",p);
	
	printf("You Enter number is %d", *p);  	
  	
  	return 0;
  } 
 
 
 
 
 
 
 free
 函数原型
 void free(void *pty);
 free函数释放ptr参数指向的内存空间.该内存空间必须是由malloc calloc realloc 函数申请的.
 否则,该函数将导致未定义行为,如果pty参数是NULL,则不执行任何操作.注意:该函数并不会修改ptr参数的值,
 所以调用后它仍然指向原来的地方(变为非法空间). 
 
 #include <stdio.h>
 #include <stdlib.h>
 int main()
 {
        int *p;
        p = (int *) malloc(sizeof(int));
        if(p == NULL)
        {
                printf("You Don't Have many money : ");
                exit(1);
        }

        printf("Please You Enter A number : ");
        scanf("%d",p);

        printf("You Enter number is : %d", *p);

        free(p);

        printf("You Enter number is : %d", *p);
													//可以看到free释放完malloc 定义的指针p, 最终的指针内容被释放变为0 
        
        
    回显 
    
    Please You Enter A number : 123
	You Enter number is : 123
	You Enter number is : 0
	
	
	导致内存泄露!!!
	1.隐式内存泄漏(即用完内存块没有即使使用free函数释放)
	2.丢失内存块地址   p = (int *)malloc(sizeof(int)); ---> 指向内存地址  int num = 520
					   *p = &num  一开始调用内存指向的地址被重新赋值找不到之前的地址,就会
					   产生丢失内存块地址	
	
	初始化内存空间 
	memset 	使用一个常量字节填充内存空间 
	memcpy	拷贝内存空间 
	memmove	拷贝内存空间 
	memcmp	比较内存空间 
	memchr	在内存空间中搜索一个字符 
	memset(初始化的内存块,初始化的常量,内存块的尺寸)
	
	
	calloc
	void*calloc(size_t nmemb , size_t size) 
	calloc函数在内存中动态地申请nmemb个长度为size的连续内存空间
	即申请的总空间为nmemb * size,这些内存空间全部初始化为0 
	
	
	等价式子 
	calloc()
	int *p = (int *)calloc(8,sizeof(int));
	
	malloc
	int *p = (int *)malloc(8 * sizeof(int));
	memset(p,0,8*sizeof(int));

 }
~                                                                                                
~                
 	realloc 是 memcpy的简化题  
	  
 #include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
        int i;
        int *p1 = NULL;
        int *p2 = NULL;

        p1 = (int *)malloc(10 * sizeof(int));

        for(i=0;i<10 ;i++)
        {
                p1[i] = i;
                //printf("%d\n",p1[i]);
        }

        p2 = (int *)malloc(20 * sizeof(int));

        //把P1中的数据拷贝到P2中

        memcpy(p2 , p1 , 11);

        for(i = 0; i < 20 ; i++)
        {
                printf("%d\n",p2[1]);
        }


        free(p1);
        free(p2);

    memcpy的原型
	
	
	realloc 
	void * realloc(void *ptr , size_t size)
	realloc函数修改ptr指向的内存空间大小为size字节
	
	如果新分配的内存空间大小比原来的大,则就内存块的数据不会发生改变
	如果新的内存空间大小小于旧的内存空间,则会造成数据丢失,慎用! 
 	
 
 	C语言得内存布局规律
	 
	内存地址越高  内存地址高 
	内存地址越低  内存地址低
	 
	 局部变量
	 动态申请中的内存空间
	 全局变量		未初始化 
	 静态变量		未初始化
 	 静态变量 		初始化
	 全局变量		初始化
	 字符串常量
	 函数	  
 
	
	------>	高地址   	命令行参数和环境变量 
	------>	
	------>	栈 
	------>
	------>
	------>				未使用的内存空间 
	------>	
	------>				
	------>	堆 
	------>	
	------>	bss段 
	------>	
	------>	数据段	
	------>	
	------>	代码段 
	
-----------------------------------------------------------------------------------	 	
	代码段 (Text segment) 
	
	存放程序执行代码的区域,大小在程序运行之前就已确定,在内存区域中属于只读,
	也可能存储一些变量,字符串 
	
----------------------------------------------------------------------------------- 	
	数据段 (Initialized data segment)
	
	存放初始化的全局变量和局部静态变量 
	
-----------------------------------------------------------------------------------	 	
	BBS段(Bss segment / Uninitialized data segment)
	
	存放程序中未初始化的全局变量区域,BBS Block started by system 
	区段数据在程序执行前被自动初始化为0 
	
	
	实验
	
	#include <stdio.h>
	int main()
	{
		return 0;
	}
	
	gcc test.c -o test
	
	size test
	 
   text    data     bss     dec     hex 	filename
	803     248       8    1059     423 	test

	
	#include <stdio.h>
	
	int globale_uninit_var;
	
	int main()
	{
		return 0;
	}
	
	gcc test.c -o test
	
	size test
	
	text    data     bss     dec     hex 	filename
    803     248      12    1063     427 	test

	可以看到bss的数值增加 
	说明 全局变量没有进行初始化 将会存储在bss段中 
	
	
	设置静态局部变量 发现bss的数值增加
	
	
	将全局变量 和 静态局部变量进行初始化 
	text    data     bss     dec     hex 	filename
    803     256       8    1067     42b 	test
 
	发现data的值增加 
	
	说明数据段存储初始化的全局变量和静态局部 
	
	
	设置变量发现text的值变化
	
	说明代码段存储变量和字符串.
	 
	text    data     bss     dec     hex 	filename
    835     256       8    1099     44b 	test

	
	
	
-----------------------------------------------------------------------------------	 
	堆
	
	用于存放程序运行中的动态分配的内存段
	大小不固定,可动态扩展或缩小,当进行调用malloc,calloc,realloc分配内存时
	新分配的内存就被动态的加到堆上,当利用free等函数释放内存时,被释放的内存
	从堆上被剔除. 
	 
	 
	栈   ---------->   代码执行的内存区域	--------------------> 通常与堆共享一片区域 
	
	
	局部变量,函数的参数,函数的返回值   ----> 栈
	
	 
	栈 和 堆 区别
	
	
	申请放式
	- 堆  由  程序员手动申请		例: malloc calloc  realloc 调用分配内存 
	- 栈  由  系统自动分配			代码执行的内存区域 需系统分配代码执行区域 
	
	 
	释放方式
	- 堆  由  程序员手动释放		例: 程序员用free函数释放调用的内存分配 
	- 栈  由  系统自动释放	 	当程序结束时,系统自动释放程序分配的空间 
	
	
	生存周期
	
	- 堆 	生存周期由动态申请到程序员主动释放位置,不同的函数之间均可自由访问
	- 栈	生存周期由函数调用开始到函数返回时结束,函数之间的局部变量不能互相访问 
	
	 
	
	实验:
	
	
#include <stdio.h>
#include <stdlib.h>

int *func(void)
{
        int *p = NULL;

        p = (int *)malloc(sizeof(int));
        if(p == NULL)
        {
                printf("Error!");
        }

        *p = 520;

        return p;
}

int main()
{
        int *p = NULL;
        p = func;

        printf("%d\n",*p);
        free(p);

        return 0;
}
 
	
	
	一般来说在func中调用的内存分配空间赋予的值,是不会被main函数接收到,
	但是在func中 return p;将分配的指针地址返回,main函数接收到地址信息,
	就可以找到对应的函数对应的值. 
	
	
	
	宏定义
	defined
	字符串替换	
	
	文件包含  宏定义  条件编译	 --->	:编译 
	
	
	带参数 和 不带参数
	
	#define PI 3.14
	整个程序PI值 3.14
	
	宏定义一般都用大写字母组成
	
	宏定义只是进行简单的替换,编译器不会对宏定义进行语法检查 
	 
	宏定义不是说明或语句 不需要加; 
	
#include <stdio.h>

#define PI 3.14 		define 的作用域 到 undef上面为止 

int main(void)
{
	int r;
	float s;
	
	printf("请输入圆的半径:");
	scanf("%d",&r);
#undef PI 3.1415926
	s = PI * r * r ;
	printf("圆的面积是 : %.2f\n",s );
} 
	
	
	
	
	
	
	
	
*/








































 q





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值