调用java代码
#include <stdio.h>
#include <stdlib.h>
main()
{
//输出
printf("Hello world !\n");
//调用java代码
system("java HelloWorld");
//调用系统cmd里面的命令,pause 暂停执行
system("pause");
}
基本数据类型
C的基本数据类型:char, int, float, double, signed, unsigned, long, short and voidC语言没有boolean,byte , String的数据类型 一般用 int 0 ,1 表示boolean,char 表示btye类型
#include<stdio.h>
int main(){
// sizeof() :获取到某种数据类型的长度
// %d 是一个占位符
printf("char占用的长度为 %d\n" , sizeof(char));
printf("int占用的长度为 %d\n" , sizeof(int));
printf("float占用的长度为 %d\n" , sizeof(float));
printf("double占用的长度为 %d\n" , sizeof(double));
printf("long占用的长度为 %d\n" , sizeof(long));
printf("short占用的长度为 %d\n" , sizeof(short));
printf("signed int占用的长度为 %d\n" , sizeof(signed int));
// signed 和 unsigned用来指定某个数据类型是有符号的还是无符号的
//它只能修饰int、long,而不能修饰 double float浮点双精度的类型
//java中的long占用8个字节 c语言 4个字节
system("pause");
return 0;
}
输出类型的标示符
#include<stdio.h>
int main(){
int i = 3555;
long l = 333333;
char c ='A';
float f = 3.141592;
double d = 3.33333;
printf("int %d\n",i); //int输出类型的标示符为%d
printf("long %ld\n",l); //int输出类型的标示符为%ld
printf("char %c\n",c); //...
printf("float %f \n",d); //...
printf("double %lf \n",d);//...
printf("i的16进制 %#x\n",i); //16进制输出类型的标示符为%x
system("pause");
}
输出函数
#include <stdio.h>
#include <stdlib.h>
main()
{
//输出
printf("Hello world !\n");
//调用java代码
system("java HelloWorld");
//调用系统cmd里面的命令,pause 暂停执行
system("pause");
}
输入函数
#include<stdio.h>
int main(){
//定义了一个长度为10的char数组
char arr[10];
//接收字符串并放到arr数组中
scanf("%s", arr);
//打印字符串
printf("字符串%s \n ", arr);
system("pause");
}
什么是指针
#include<stdio.h>
int main(){
int i =3 ;
// 定义个一个变量 名字p ,变量的类型是int* 的类型 ;也可以写成int* p, int *p;
// int* 的类型就是一个指针类型 ,指针用来表示一个地址
// p是一个变量, 这个变量里面存放的数据类型 , 必须是一个指针类型的数据( p里面的存放的数据必须是一个地址)
int* p ;
//&取地址符号,可以把变量的一个地址取出来 ,p里面存放的是i的地址
//变量名i 程序编译运行的系统会自动把变量名和对应的地址产生对应关系
p = &i;
printf("i的地址%#X\n",&i);
//* 星号操作符 , 取到某个地址里面存放的数据
printf("p所指向地址里面的数据内容是 %d\n " ,*p);
// *p 和 i 是同一个东西
//改变*p的值 ,i的值也回改变
*p=88;
printf("i数据内容是 %d\n " ,i);
// 改变i的值 ,*p的值也回改变
i = 99;
printf("改变后*p的值 %d\n " ,*p);
// p 跟 i 没有关系, 修改p的值 不会影响i的值 , 修改i的值 也不会影响p的值
system("pause");
}
指针的常见错误
1. 指针p未经赋值, 不能使用 *p的数据
2. 指针类型的变量,只能存放地址类型的数据 .
3. 不同类型的指针变量,不同互相赋值
#include<stdio.h>
int main(){
// p指针变量虽然被定义出来了, 没有赋初值, 里面的内容垃圾值 .
int* p ; // p里面的地址不确定
// 获取一块不确定的内存地址里面的值 .
printf("p所指向的值是 %d\n",*p);
p = 33; //错误的 33是一个int类型 ,数据类型不同
char c ='A';
p = &c; // 错误的&c获得的是 字符的地址 , p 是一个int数据类型的地址
system("pause");
}
指针和指针变量的关系
快速传递数据(指针表示地址)
返回一个以上的值(返回一个数组或者结构体的指针)
表示复杂的数据结构(结构体)
方便处理字符串
指针有助于理解面向对象
指针-快速传递数据
要在另外一个函数中 去更改主函数的值
1. 把要修改的变量的的地址作为参数传递到子函数里面
2. 子函数里面 要接受到 主函数传递的地址 ( 子函数的形参是一个指针类型的形参)
3. 通过使用地址对应的变量, 修改主函数里面的某个变量
#include <stdio.h>
#include <stdlib.h>
void swap(int i ,int j){
int temp;
temp = i;
i = j;
j = temp;
}
//需要获取到两个变量的引用, 需要两个变量的地址作为形参传递过来 .
void swap2(int* p ,int * q ) {
int temp;
temp = *p;
*p = *q;
*q = temp;
}
main()
{
int i = 3;
int j = 5;
//swap(i,j); //值传递不会互换
swap2(&i,&j); //引用传递,传递内存地址会互换
printf("i的值是%d\n",i);
printf("j的值是%d\n",j);
system("pause");
}
#include <stdio.h>
#include <stdlib.h>
// 指针参数 接受两个地址
//通过指针 让函数返回了两个值
void f1(int* p , int* q ){
*p = 8;
*q = 10;
}
main()
{
int x =3 ;
int y =5;
f1(&x, &y);
printf("x的值是 %d\n",x);
printf("y的值是 %d\n",y);
system("pause");
}
指针和数组的关系
一维数组名是个指针常量,它存放的是一维数组第一个元素的地址
java中定义数组可以用:int[] arr, int arr[] ,在C中只能用int arr[]
c语言不检查数组的下标 ,容易产生很危险的情况缓冲区溢出
#include <stdio.h>
#include <stdlib.h>
int main(){
int arr[10]={1,2,3,4,5,6,7,8};
printf("数组的第一项是 arr[0]= %d\n",arr[0]);
//下边返回2293672 ,说明 c语言不检查数组的下标
printf("数组的最后一项是 arr[11]= %d\n",arr[11]);
//arr是数组名,代表一个首地址
printf("arr的值 %#X\n",arr); //数组地址 0X22FF40
printf ("数组的第一个元素的arr[0]的地址 %#X\n",&arr[0]); //0X22FF40
//把指针移动到下一个位置 , 获取这个地址里面的值 ,*(arr+1) ,获取数组第二个元素
// *(arr+1) 和arr[1] 代表的是同一块内存,指向的是同一个变量
printf ("数组的第二个元素的值%d\n", *(arr+1));
system("pause");
}
确定一个c语言的数组
确定一个数组需要两个参数 1,数组的首地址 ,2. 数组的长度
#include <stdio.h>
#include <stdlib.h>
void printArr(int * p , int len){
int i =0 ;
for(;i<len;i++)
{
//通过指针去获取数组里面的每一个值
// printf("arr[%d]= %d\n", i, *(p+i)) ;
//通过数组下标打印数组里面的每一个值
//数组的首地址 , 可以当成数组名去使用
printf("arr[%d]= %d\n", i, p[i]) ;
// *(p+i) p[i]代表的是同一块内存空间 指向的是同一个变量
}
}
main()
{
int arr[5] = { 1,2,3,4,5};
//arr存放的数组的首地址
printArr(arr ,5 );
system("pause");
}
指针的运算
#include<stdio.h>
int main(){
int i = 3;
int j = 5;
int* p = &i;
int* q = &j;
// p-q; 没有逻辑意义 p 天津门牌号30 q 北京的门牌号 50
char arr[20]={'a','b','c','d'};
printf("%c" , *(arr + 1));
char* c1 = &arr[5];
char* c2 = &arr[10];
printf("c2和c1之间的距离 %d\n" ,c2-c1);
// c2-c1 =5 (偏移量)
system("pause");
}
指针-方便处理字符串
#include<stdio.h>
int main(){
//定义了一个字符串 \0;
char* str = "hello c language";
printf("%s", str);
system("pause");
}
*号的三种含义
1.乘法
2.定义指针变量 int * p;//定义了一个名字叫p的变量,能够存放int数据类型的的地址
3.指针运算符,//如果p是一个已经定义好的指针变量 则*p表示以p的内容为地址的变量
内存动态分配
// malloc memory allocate 内存分配
#include<stdio.h>
int main(){
int i ; //栈内存中 静态的分配一个空间 4byte
int* p = (int*)malloc(4); // 参数的要申请的内存空间的大小
// 在堆内存中申请一块空间
// 函数的返回值是申请的空间的首地址
// int* p = malloc(4); 在内存中申请了8byte的空间
// 4byte是静态申请,用来存放 p指针的内容
// 4byte是动态申请的, malloc申请 大小为4byte 可以存放一个int类型的数据
*p = 5;
printf("*p的值是 %d \n", *p);
//回收掉申请的空间
free(p); //p 参数是申请到的空间的首地址
//编译,运行没有问题 , 逻辑问题 .
// p地址对应空间已经被释放掉了.
printf("*p的值是 %d \n", *p);
system("pause");
}
动态的创建数组
#include<stdio.h>
void printArr(int* p, int len){
int i= 0;
for(;i<len;i++){
printf("数组的第%d个元素的值为%d\n",i, *(p+i));
}
free(p);
printf ("数组的第3个元素的值为%d\n", *(p+3));
}
int main(){
printf("请输入数组的大小\n");
int len;
//获取键盘的输入的int的数据
scanf("%d",&len);
//动态的创建大小为 4*len bytes 内存空间
int* p =(int* )malloc(sizeof(int) * len);
int i=0;
for(;i<len;i++){
printf("请输入数组的第%d个元素的值\n",i);
scanf("%d", (p+i));
}
printArr(p, len);
system("pause");
}
动态改变数组的长度
在使用数组的时候,如果发现内存空间不够用了,可以用realloc函数重新分配数组的长度
#include<stdio.h>
#include<malloc.h> // malloc 和 realloc 所在的头文件
int main(){
//创建一个大小为5的内存空间
int* p =(int*) malloc(5*sizeof(int));
p[0] = 1;
p[1] = 2;
p[2] = 3;
p[3] = 4;
p[4] = 5;
//realloc第一个参数是数组的首地址,第二个参数是修改后的空间的大小
p = (int* )realloc(p,6*sizeof(int));
p[5] = 6;
printf("%d\n", p[5]);
//释放内存
free(p);
system("pause");
}
多级指针
#include<stdio.h>
int main(){
int i = 5;
int* p = &i; //int * 可以存放 int类型的变量的地址
int** q = &p; // int** 可以存放 int* 类型变量的地址
int*** r = &q; //int *** 可以存放的是int** 类型的地址
printf("i 的值是 %d \n", ***r);
system("pause");
}
函数的指针
#include<stdio.h>
int add(int x, int y ){
return x+y;
}
int main(){
// 定义普通函数 int fp( int x, int y);
// 定义一个函数的指针 int (*fp)(int x, int y);
int (*fp)(int x, int y);
// 函数的指针赋值 fp是一个变量 ,变量表示的是一个 函数的入口地址
fp = add ;
printf("函数的首地址 %#X\n", fp);
// 调用 指针函数
printf("%d\n", fp(3,5));
system("pause");
}
结构体
#include<stdio.h>
struct Student
{
int age; //4
float score; //4
long id; //4
char sex; //1
};
int main(void)
{
struct Student st={80,55.6f,100010,'F'};
printf("年龄为%d\n", st.age);
//查看结构体的长度
printf("student结构体的长度为 %d \n" ,sizeof(st));
// 输出的长度按理应该是13,结果却是16,结构体 编译器不同 ,他有不同的数据对齐方式 ,
// 导致结构体 在内存中的长度可能会有区别 .
system("pause");
}
结构体的指针
#include<stdio.h>
struct Student
{
int age; //4
float score; //4
long id; //4
char sex;
};
int main(void)
{
struct Student st={80,55.6f,100010,'F'};
// 定义结构体的指针
struct Student* sp = &st;
//-> 获取结构体里面的 某个字段
printf("学生的年龄为%d \n" , sp-> age);
// sp-> age 在程序执行 (*sp).age
system("pause");
}
结构体三种初始化方法
//第一种方式
struct Student
{
int age;
float score;
char sex;
}
//定义一个名字叫st1 的结构体
struct Student st={80,55.6f,100010,'F'};
//第二种方式
struct Student2
{
int age;
float score;
char sex;
} st2; //直接定义一个名字叫st2 的结构体
//第三种方式
struct
{
int age;
float score;
char sex;
} st3 // 类似于 java的匿名内部类
枚举
#include <stdio.h>
enum WeekDay
{
Monday = 5,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
};
int main(void)
{
//int day;
enum WeekDay day = Sunday;
printf("%d\n",day);
system("pause");
return 0;
}