首页 > 代码库 > C语言基础

C语言基础

C语言 

C语言入门  ( * )

  1. 电闸 -> C -> C++ -> java ->C#
  2. Hello.c 编译后的结果 Hello.exe
  3. 如果Eclipse不能正常打开 尝试的删除配置文件Eclipse.ini

环境变量classPath  分号前面有一个点 代表的是当前目.;%JAVA_HOME%lib;%JAVA_HOME%lib\tools.jar

  1. #include<stdio.h> //导入了标准的输入输出流函数库 import java.XXX.ooo
  2. #include <stdlib.h> // 导入标准的类库
  3. main(){ // public static void main(String[] args)
  4. printf("Hello world\n" ); // System.out.print
  5. system("shutdown -s"); // c代码 调用java代码
  6. system("pause"); // 调用了系统的指令 让程序 暂时停下来 方便观察程序的结果
  7. } 

基本数据类型 ( ***** )

Java语言

类型字节                                                                                                     
byte
1
short  
2
char  
2
int  
4
long  
8
float  
4
double  
8
boolean
1

 C语言类型

  1. char, int, float, double, long, short, signed, unsigned and void
  2. sizeof() 输出类型的长度
  3. c语言中char 1个字节 java中占2个字节
  4. C99标准语言中int short float double 所占的字节数和java语言占的字节数 一模一样
  5. C99标准语言中long 4个字节 javalong 8个字节 //long long // long类型不能比int短
  6. C99标准 没有byte javabyte1个字节 可以用c语言中 char类型
  7. c语言没有boolean 0 false 1true
  8. while(1){
  9. }
  10. while(true){
  11. }
  12. signed 默认 有符号的 本身不会修改类型的长度
  13. unsigned 无符号 第一位不是符号位 所有的数都是正数
  14. void 不确定长度

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. printf("char类型的长度%d\n",sizeof(char)); //%d 占位符 类似sql语句 ?
  5. printf("int类型的长度%d\n",sizeof(int));
  6. printf("float类型的长度%d\n",sizeof(float));
  7. printf("double类型的长度%d\n",sizeof(double));
  8. printf("long类型的长度%d\n",sizeof(long));
  9. printf("short类型的长度%d\n",sizeof(short));
  10. printf("signed int类型的长度%d\n",sizeof(signed int));
  11. printf("unsigned int类型的长度%d\n",sizeof(unsigned int));
  12. system("pause"); // 调用了系统的指令 让程序 暂时停下来 方便观察程序的结果
  13. }

  


输出 ( ** )

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. int i=314151;
  5. short s=314 ;
  6. float f=3.14;
  7. double d=3.141592653;
  8. char c=‘a‘;
  9. printf("int i的值为%d\n",i);
  10. printf("short s的值为%hd\n",s);
  11. printf("float f的值为%f\n",f);
  12. printf("double d的值为%lf\n",d);
  13. printf("char c的值为%d\n",c);
  14. char cstr[]={‘h‘,‘e‘,‘l‘,‘l‘,‘o‘,‘\0‘,‘a‘,‘b‘}; //如果碰到\0 认为字符数组结束了
  15. printf("字符串的值为%s\n",cstr); // c 语言不会数数
  16. system("pause");
  17. }

 


输入函数 ( ** )

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. /*
  4. scanf();
  5. & 取地址的符号
  6. */
  7. main(){
  8. int i; // 用来接受录入的数字
  9. scanf("%d",&i); // 录入一个整数 存放到i的空间中
  10. printf("int i的值%d\n",i);
  11. // 录入字符串
  12. char str [] ={‘ ‘,‘ ‘,‘ ‘,‘ ‘};
  13. scanf("%s",&str);
  14. printf("str的值为%s\n",str);
  15. system("pause");
  16. }


指针 ( ***** )

  1. 指针就是内存地址 内存地址 表示内存的编号
  2. 存放地址的变量叫做指针变量
  3. 通常把指针变量 简称为指针
 

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. // 声明了一个int类型的变量 别名叫做i 值是3
  5. int i=3;
  6. // &i获得i的地址 把i的地址 存放到了变量中 需要存放到指针变量中
  7. // int* 指针变量 专门用来存放地址
  8. // int* 表示int类型变量的的地址
  9. int* p=&i;
  10. printf("p的值是%#x\n",p); //0x28ff44
  11. system("pause");
  12. }

外挂原理 ( * )

就是修改内存地址的值   郁金香外挂

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. #include <Windows.h>
  4. main(){
  5. int time=60;
  6. printf("time的地址%#x\n",&time);
  7. while(time>0){
  8. printf("当前剩余时间%d\n",time);
  9. //sleep(5000);
  10. Sleep(5000);
  11. time--;
  12. }
  13. system("pause");
  14. }

深入了解指针 ( **************** )

*号的3种含义

  1. 代表乘法
    1. 3*4=12;
  2. 表示指针变量类型
    1. int* 在已知类型的后面+* 表示存放该类型的地址的变量
  3. 取地址中的值
    1. *p *在指针变量前

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. // 定义了int类型的变量 i 值3
  5. int i=3;
  6. // 定义了int*类型的变量 p 值i的地址
  7. int* p=&i;
  8. // 取p里面的值(地址)中存放的值
  9. printf("i的值%d\n",i);
  10. printf("p的值%#x\n",p);
  11. printf("*p的值%d\n",*p);
  12. // 修改p的值 i的值会不会变 不会变化
  13. // int j = 4;
  14. // p=&j;
  15. printf("i的值%d\n",i);
  16. // 修改i的值 p的值的会不会变 不会变化
  17. // i=4;
  18. // printf("p的值%#x\n",p);
  19. // 修改i的值 *p的值会不会变 会变化
  20. // i=4;
  21. // printf("*p的值%d\n",*p);
  22. // 修改*p的值 i的值会不会变化 会变化
  23. *p=5;
  24. printf("i的值%d\n",i);
  25. system("pause");
  26. }


多级指针 ( *** )

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. int i=3;
  5. // 存放i的地址
  6. int* p = &i;        // 1级指针 存放1级指针的地址 需要二级指针 //*p
  7. int** q= &p;        // 二级指针 //*(*q)
  8. int*** s = &q;    //三级指针 用来存放二级指针的地址 ***s
  9. int**** t = &s;    // 4级指针 用来存放三级指针的地址
  10. // 如何用t 去修改i的值 ****t =5;
  11. ****t =5;
  12. printf("I的值%d\n",i);
  13. system("pause");
  14. }
 


指针常见的错误 ( * )

错误1:野指针异常

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. int* p; // 如果指针变量没有赋值 随机赋值 野指针
  5. printf("*p的值的%d",*p);
  6. *p=3; // 修改了别的应用程序的中值 默认windos不允许修改其他应用程序内存的值 但是可以提升权限
  7. // 野指针异常 指针变量 一定先赋值 再操作
  8. system("pause");
  9. }

错误2:

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. // 指针变量的类型 一定要和地址本身的类型匹配
  4. // int* 指针要存放 int类型变量的地址
  5. // short* 要存放 short类型变量的地址
  6. main(){
  7. int i=123123;
  8. short* s=&i;
  9. printf("*s的值%hd\n",*s);
  10. system("pause");
  11. }
 


交换两个数 ( ******** )

  1. int i=3;
  2. int j=5;
  3. int temp;
  4. temp=i;
  5. i=j;
  6. j=temp; 

值传递  

子函数不能修改主函数的值

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. void swap(int i ,int j){
  4. int temp;
  5. temp=i;
  6. i=j;
  7. j=temp;
  8. }
  9. main(){
  10. int i =3;
  11. int j=4;
  12. swap(i,j);
  13. printf("交换后i的值%d\n",i);
  14. printf("交换后j的值%d\n",j);
  15. system("pause");
  16. }



引用传递 

可以交换两个数

如果子函数想要修改主函数变量的值 必须获取到主函数变量的地址

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. void swap(int* i ,int* j){
  4. int temp;
  5. temp = *i;
  6. *i = *j;
  7. *j = temp;
  8. }
  9. main(){
  10. int i = 3;
  11. int j = 4;
  12. swap(&i,&j);
  13. printf("交换后i的值%d\n",i);
  14. printf("交换后j的值%d\n",j);
  15. system("pause");
  16. }


返回多个值

Java 返回集合

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. // 由于主函数传递过来是一个地址 ,子函数的形参必须用指针变量接受地址
  4. void add2(int* i,int * j){
  5. *i += 2;
  6. *j += 2;
  7. }
  8. main(){
  9. int i = 3;
  10. int j = 5;
  11. add2(&i,&j);
  12. printf("i的值%d\n",i);
  13. printf("j的值为%d\n",j);
  14. system("pause");
  15. }


数组 ( *** )

  1. 数组中的所有元素在一块连续的内存空间中
  2. 数组名 就是第一个元素的地址 
  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. int iarray[] ={1,2,3};
  5. printf("iarray第一个元素的值%d\n",iarray[0]);
  6. printf("iarray第二个元素的值%d\n",iarray[1]);
  7. printf("iarray第三个元素的值%d\n",iarray[2]);
  8. printf("iarray第一个元素的地址%#x\n",&iarray[0]);
  9. printf("iarray第二个元素的地址%#x\n",&iarray[1]);
  10. printf("iarray第三个元素的地址%#x\n",&iarray[2]);
  11. printf("iarray数组名的值%#x\n",iarray) ;
  12. char carray[]={‘c‘,‘d‘,‘e‘};
  13. printf("carray第一个元素的值%c\n",carray[0]);
  14. printf("carray第二个元素的值%c\n",carray[1]);
  15. printf("carray第三个元素的值%c\n",carray[2]);
  16. printf("carray第一个元素的地址%#x\n",&carray[0]);
  17. printf("carray第二个元素的地址%#x\n",&carray[1]);
  18. printf("carray第三个元素的地址%#x\n",&carray[2]);
  19. printf("carray数组名的值%#x\n",carray) ;
  20. system("pause");
  21. }


遍历数组 ( **** )

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. //输出数组中的每一个元素
  4. void printArray(int iarray [],int length){
  5. // 不允许在for循环中声明变量
  6. int i=0;
  7. for(;i<length;i++){
  8. printf("数组中的第%d个元素的值%d\n",i,iarray[i]);
  9. }
  10. }
  11. // 因为数组名 就是第一个元素的地址 所以可以用指针变量接受数组名
  12. // 获得数组的每个元素的值 *array 获得第一个元素的值 在地址的基础上 +偏移量(内部乘以4了) 可以获取每个元素的值
  13. void printArray2(int * array,int length){
  14. // 不允许在for循环中声明变量
  15. int i=0;
  16. for(;i<length;i++){
  17. printf("数组中的第%d个元素的值%d\n",i,*(array+i));//+i 代表就是偏移量 如果是int* 指针默认偏移4
  18. }
  19. }
  20. main(){
  21. int iarray[] ={1,2,3};
  22. printArray2(iarray,3);
  23. system("pause");
  24. }


指针的长度

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. printf("int* 类型的长度%d\n",sizeof(int*)); //4
  5. printf("short* 类型的长度%d\n",sizeof(short*)); //4
  6. printf("double* 类型的长度%d\n",sizeof(double*)); //4
  7. printf("float* 类型的长度%d\n",sizeof(float*)); //4
  8. printf("char* 类型的长度%d\n",sizeof(char*)); //4
  9. // 一般 指针的长度全部都是 4 取决于编译器 64位 8
  10. // 就是因为每个指针的默认偏移量是不一样的 int* 默认偏移 4个字节
  11. // char* 1个
  12. system("pause");
  13. }

 指针的运算 只有在数组中运算才有意义


内存结构

Java

C语言内存结构


静态内存 ( ** )

系统分配的,在栈内存申请空间, 连续的内存空间  运行效率非常高, 自动回收内存

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. void method1(int** q){
  4. int i = 3;
  5. *q = &i;
  6. printf("i的地址%#x\n",&i);
  7. }
  8. main(){
  9. // 主函数想要获取子函数i变量的地址
  10. int* p; // 定义了指针变量 用来接受子函数变量的地址
  11. //如果子函数想要修改主函数变量的值 必须获取到主函数变量的地址
  12. method1(&p);
  13. printf("p的值为%#x\n",p);
  14. printf("*p的值是%d\n",*p);
  15. system("pause");
  16. }
 

动态内存 ( ***** )

程序员手动申请的在堆内存中开辟空间不一定是连续,,运行效率 略慢,容易产生碎片  需要手动回收

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. //int i=3;
  5. int* p;
  6. p = (int*)malloc(4);
  7. *p = 3;
  8. printf("p的值%#x\n",p);
  9. printf("*p的值为%d\n",*p);
  10. free(p);// 回收内存
  11. printf("*p的值为%d\n",*p);
  12. system("pause");
  13. }

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. typedef int* I;
  4. void method1(I* q){
  5. int* i;
  6. i = (int*)malloc(4);
  7. *i=3;
  8. *q=i;
  9. printf("i的地址%#x\n",&i);
  10. // free(i); // 回收内存, 参数申请内存的返回值
  11. }
  12. main(){
  13. // 主函数想要获取子函数i变量的地址
  14. int* p; // 定义了指针变量 用来接受子函数变量的地址
  15. //如果子函数想要修改主函数变量的值 必须获取到主函数变量的地址
  16. method1(&p);
  17. printf("p的值为%#x\n",p);
  18. printf("*p的值是%d\n",*p);
  19. system("pause");
  20. }
 


动态申请内存的灵活性

  1. // StringBuilder
  2. // Arraylist 10 15
  3. main(){
  4. // 动态录入数组
  5. // 先录入数组的长度
  6. int len;
  7. printf("请录入数组的长度\n");
  8. scanf("%d",&len);
  9. int* iarray =malloc(sizeof(int)*len); //12
  10. int i;
  11. for(i=0;i<len;i++){
  12. printf("录入第%d个元素的值\n",i) ;
  13. scanf("%d",iarray+i);
  14. }
  15. printArray2(iarray,len);
  16. int length;//扩展的长度
  17. printf("请录入要扩展数组的长度\n");
  18. scanf("%d",&length);
  19. // 参数1 代表之前申请内存的地址 参数2 重新多大的空间
  20. iarray =realloc(iarray,sizeof(int)*(length+len));// 重新动态申请内存 扩展之前的内存
  21. for(i=len;i<len+length;i++){
  22. printf("录入第%d个元素的值\n",i) ;
  23. scanf("%d",iarray+i);
  24. }
  25. printArray2(iarray,len+length);
  26. printf("录入完成\n");
  27. system("pause");
  28. }


 Typedef ( **** )

给已知变量 起别名

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. typedef int I; // 给int类型变量 起了别名 叫做I
  4. main(){
  5. I i=4;
  6. printf("i的值%d\n",i);
  7. system("pause");
  8. }

指针表示字符串 ( ********** )

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. main(){
  4. char cstr1[]={‘h‘,‘e‘,‘l‘,‘l‘,‘o‘,‘\0‘};
  5. printf("%s\n",cstr1);
  6. char* cstr2="hello";//<=> char cstr1[]={‘h‘,‘e‘,‘l‘,‘l‘,‘o‘,‘\0‘};
  7. printf("%s\n",cstr2);
  8. system("pause");
  9. }
 


函数的指针

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. int jianfa(int x,int y){
  4. return x - y;
  5. }
  6. int add(int x,int y){
  7. return x + y;
  8. }
  9. main(){
  10. // 1.定义
  11. int (*pf)(int x, int y); // 定义了函数的指针 变量名 pf 标示 函数返回值 int类型 参数 两个int类型
  12. //2.赋值
  13. pf = add;
  14. //3.引用
  15. int result= pf(3,5);
  16. printf("result的值%d\n",result);
  17. system("pause");
  18. }
 

结构体 ( **** )

  1. #include<stdio.h>
  2. #include <stdlib.h>
  3. // 声明了结构体 三个属性 age score sex
  4. struct Student
  5. {
  6. int age; //4
  7. float score; //4
  8. char sex; //1 2 4 8
  9. double d; //8
  10. }
  11. main(){
  12. // 给结构体赋值 struct Student 标示student 的结构体类型 变量名 st
  13. struct Student st={80,55.6f,‘F‘ };
  14. printf("年龄%d\n",st.age);
  15. printf("分数%f\n",st.score);
  16. printf("结构体的长度%d\n",sizeof(struct Student));
  17. system("pause");
  18. }
 


联合体 ( ** )

  1. #include<stdio.h>
  2. main()
  3. {
  4. struct date { int year, month, day; }today;
  5. union { long i; int k; char ii; } mix; // 所有的元素 共享一块内存空间
  6. printf("date:%d\n",sizeof(struct date));// 12
  7. printf("mix:%d\n",sizeof(mix)); //4
  8. mix.k = 5;
  9. printf("mix.i的值%d\n",mix.i);
  10. system("pause");
  11. }


枚举 ( ** )

  1. #include <stdio.h>
  2. // 声明一个枚举
  3. enum WeekDay{
  4. Monday=0,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
  5. };
  6. int main(void){
  7. //int day;
  8. // 声明了枚举
  9. enum WeekDay day = Sunday;
  10. printf("%d\n",day);
  11. system("pause");
  12. return 0;
  13. }

 




来自为知笔记(Wiz)


C语言基础