C语言学习(第一天)
2018-07-22 本文已影响0人
arkliu
C语言基本数据类型
// java数据类型 和长度int 4个字节 double 8个字节 float 4个字节 long 8个字节
// short 2个字节 boolean 1个字节 char 2个字节 byte 1个字节
// char, int, float, double, signed, unsigned, long, short and void
// c语言中 数据类型比java少一些 在c语言中没有 boolean类型的数据 int 1 代表真 0 代表假
// c 语言中没有String类型的数据 java中表示一个字符串 String , c语言中表示字符串 通过char类型的数组来表示字符串
// c 语言没有byte类型 所有用char的类型表示byte类型
#include <stdio.h>
#include <stdlib.h>
// sizeof(); c语言的一个函数 可以把 某种数据类型的长度获取出来 int
main()
{ // %d 类似sql语句的? 占位符
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));
//signed, unsigned, 数据类型的修饰符
// signed int ; 代表的是有符号的int的数据
// unsigned int ; 无符号的int数据
printf("signed int的长度为%d\n", sizeof( signed int));
printf("unsigned int的长度为%d\n", sizeof( unsigned int));
// 符号的修饰符 只能修饰 整数类型的数据 long int
// 不能修饰 浮点型的数据 float double
// printf("signed float的长度为%d\n", sizeof( signed float));
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
输入和输出函数
/*%d - int
%ld – long int
%c - char
%f - float
%lf – double
%x – 十六进制输出 int 或者long int 或者short int
%o - 八进制输出
%s – 字符串
Int len;
Scanf(“%d”,&len);*/
#include <stdio.h> // java import xxx.xx.pack 引用函数的声明
#include <stdlib.h>
main() // 程序的入口函数
{ int i = 3;
float f = 3.1415;
double d = 6.2815;
char c = 'A'; //通过单引号定义字符
short s = 2;
printf("int i=%d\n",i);
printf("float f=%f\n",f);
printf("char c=%c\n",c);
printf("double d=%lf\n",d);
printf("short s=%d\n",s);
/*char arr[20] ; //定义一个长度为20的数组
scanf("%s",arr); // 从键盘接受一个字符串,放在c数组里面
printf("s =%s\n",arr);
*/
int j ;
scanf("%d", &j);//&代表的是取地址
printf("j=%d\n",j);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
指针入门
#include <stdio.h>
#include <stdlib.h>
main()
{
//指针是什么? 指针就是一个地址
//地址代表的就是一块内存空间
int i =5;// 定义一个int 类型的变量i 值 =5
printf("i的地址 %#X\n",&i);
//获取i的地址
// &i;
//定义一个指针变量
int* p ; // 指针变量 定义一个int* 类型的变量p
//int *p, int * p;
p = &i; // 就是把i的指针赋给指针变量p ,现在指针变量p里面存放的内容(数据) 就是i的地址
printf("p里面的内容为(i的地址) %#X\n",p);
//*号 操作符
// *号的几种含义
//1 . *号放在某种数据类型的后面,代表就是这种数据类型的指针 int* float*
//2 . *号 代表一个乘法符号 3*5 = 15;
//3 . *号放在一个指针变量的前面 -> 代表取这个指针变量所存放的地址里面对应的数据
printf("i=%d\n",i);
printf("*p的值%d\n",*p);
// 改变p的值 会不会影响i的值?
//p = NULL;
// printf("i=%d\n",i);
// 改变i的值 会不会影响p的值?
// i = 100;
// printf("p里面的内容为(i的地址) %#X\n",p);
// 通过上述实验 p和 i 是两个不同的变量 ,改变i的值 不会影响 p的值,同理,更改p的值 也不会影响i的值
// 更改*p的值 会不会影响i的值
// *p = 88;
// printf("i=%d\n",i);
// 更改i的值 会不会影响 *p的值呢?
// i = 99;
// printf("*p的值%d\n",*p);
//*p 和i 其实代表的是同一个变量,代表是同一块内存空间
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
C语言指针实现数据交换
#include <stdio.h>
#include <stdlib.h>
// 问 java 中有值传递和引用传递 吗? 他们的区别是什么?
// 其实在java中只有值传递 , 没有引用传递
// Person p = new Person(); p里面存放的内容 就是person对象的地址
void swap2(int* p , int* q){ // 传递的形参为 i 和j 变量的地址
// *p 代表 i *q 代表就是 j
int temp;
temp = *p;
*p = *q;
*q = temp;
}
void swap1(int i ,int j){ // 形参 i 和j 跟主函数里面的i和j是两个不同的变量
printf("子函数 i 地址%#X\n",&i);
printf("子函数 j 地址%#X\n",&j);
int temp;
temp = i;
i = j;
j = temp;
}
main()
{
//利用指针 可以在子函数里面修改主函数里面的数据
int i = 3;
int j = 5;
printf("i=%d\n",i);
printf("j=%d\n",j);
printf("主函数 i 地址%#X\n",&i);
printf("主函数 j 地址%#X\n",&j);
/*/交换两个数字
int temp;
temp = i;
i = j;
j = temp;
*/
// swap1(i,j);
swap2(&i,&j);
printf("交换后\n");
printf("i=%d\n",i);
printf("j=%d\n",j);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
指针的常见错误
#include <stdio.h>
#include <stdlib.h>
main()
{
int* p; //定义一个指针变量 垃圾值 -> 野指针
//printf("*p=%d\n",*p);
// 指针变量如果没有赋值就不能使用
int d = 32;
char* c; ; // 编译错误 不符合的指针类型
c = &d;
printf("*p = %c\n",*c);
类型不相同的指针不可以互相转换
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
不可以使用已经被回收的变量
#include <stdio.h>
#include <stdlib.h>
f(int** q){
int i = 3;
printf("子函数 i的地址 %#X\n",&i);
// *q 代表的就是p变量
*q = &i;
}
/**
使用指针的时候 不可以访问已经被系统回收掉的数据
子函数执行完毕后 子函数里面所有的局部变量都会别系统回收
*/
main()
{
// 希望在主函数里面去使用子函数里面的变量 i
// f();
// 希望在主函数里面得到子函数 里面int i变量的地址
int* p ; //存放子函数f中 int i的地址的一个变量
f(&p);
printf("主函数 i的地址 %#X\n",p);
printf("i的值为 %d\n",*p);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
子函数返回一个以上的值
#include <stdio.h>
#include <stdlib.h>
// public List<Person> getPersons() {};
// public byte[] getbytes(){};
/*
如果让子函数 更改主函数里面的数据
如何让子函数 返回一个以上的值
1.子函数的形参 为 主函数中要修改的变量的地址
2. 调用子函数的时候 把要修改的变量的地址 传递给子函数
3. 在子函数里面 修改这个地址里面存放的变量的内容
4. 主函数使用这个变量的时候 里面的值就发生了变化
*/
int f(int* p, int* q){
*p = 33;
*q = 55;
}
main()
{
int i = 3;
int j = 5;
f(&i,&j);
printf("i=%d\n",i);
printf("j=%d\n",j);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
使用char指针表示字符串
#include <stdio.h>
#include <stdlib.h>
main()
{
char arr[20] ={'h','e','l','l','o','\0'};
// 利用char类型指针 方便的表示一个字符串
char* arr1= "hello world";
printf("%s\n",arr1);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
指针和数组
#include <stdio.h>
#include <stdlib.h>
// 数组是一块连续的内存空间 数组名 就是内存空间的首地址
// 数组名[i] == *(数组名+i);
main()
{
/* char[] arr = new char[20];
char arr[] ;
*/
// 创建一个长度为5的int类型的数组
int arr[5] ={1,2,3,4,5};
printf("a[0]=%d\n",arr[0]);
printf("a[4]=%d\n",arr[4]);
// 逻辑上是错误的代码 数组下标越界
// printf("a[5]=%d\n",arr[5]);
// windows xp 缓冲区越界补丁
// arr是一个什么东西呢?
printf("arr = %#X\n",arr);
// 打印 数组的第一个元素的地址
printf("arr[0]地址 = %#X\n",&arr[0]);
// 打印数组中的第二个元素
printf("arr[1]=%d\n",arr[1]);
printf("arr[1]=%d\n", *(arr+1));
//问题: arr[i] *(arr+i) 代表的是同一个变量么?
// 代表的是同一块内存空间 指向的是同一个变量
//通过实验 : 数组名表示的 就是这个数组第一个元素 的首地址
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
打印数组
#include <stdio.h>
#include <stdlib.h>
#define pi 3.1415
// 写一个子函数 打印数组里面的每一个元素
void printArr(int* arr, int len){ // arr是数组的首地址 len数组的长度
int i=0;
for(;i<len;i++){ // 在c99 的语法格式下 for循环的初始化条件 不能写在 for 循环的括号里面
// printf("arr[%d]=%d\n",i,arr[i]); // arr[i] 和 *(arr+i) 代表的含义相同
printf("arr[%d]=%d\n",i, *(arr+i));
}
}
main()
{
int arr1[10]={1,2,3,4,5};
printArr(&arr1[0],10);
//1 .定义一个数组 缺陷 数组的长度 必须事先申请好
//int arr[1000]; // 这一句代码一旦执行 ,就立刻会在内存里面申请 5个内存空间 每个内存空间的大小可以存放一个int类型的数据
// 没有办法动态的增加这一块空间的大小, 也没办法减小这一块内存空间
//2. 循环赋值
//3. 打印数组里面的内容
int* arr = (int* )malloc(sizeof(int)*10);
arr = realloc(arr,sizeof(int)*8); //空间的长度为12了
int i =0;
for(;i<5;i++){
printf("请输入arr[%d]=的值\n",i);
scanf("%d",arr+i);
}
printArr(arr,5);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
指针运算
#include <stdio.h>
#include <stdlib.h>
main()
{
int i =3; //天津的某个路上 盖了一个房子 3
int j =5; // 北京的某个路上 盖了一个方法 5
int* p = &i; // p 天津的门牌号
int* q = &j; // q 北京的门牌号
// 指针的运算和数组都是紧密关联的
char arr[5]={'a','b','c','d','e'}; //一块连续的内存空间
char* p1 = &arr[2];
printf("char = %c\n", *(p1-1));
// char 内存中占用 1个字节
// int 内存 中占用 4个字节
int intarr[5]={1,2,3,4,5}; //一块连续的内存空间
int* q1 = &intarr[2];
printf("char = %d\n", *(q1-1));
// 指针的运算 按照 约定好的数据类型 偏移相对应的内存空间的大小
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
指针占用的字节大小
#include <stdio.h>
#include <stdlib.h>
main()
{
int i =3;
double d = 3.141692;
float f = 3.1423;
char c ='B';
int* ip = &i;
double* dp = &d;
float* fp = &f;
char* cp = &c;
printf("int 类型指针变量的长度为 %d\n",sizeof(ip));
printf("double 类型指针变量的长度为 %d\n",sizeof(dp));
printf("float 类型指针变量的长度为 %d\n",sizeof(fp));
printf("char 类型指针变量的长度为 %d\n",sizeof(cp));
// 在32位的操作系统上 因为程序 最大能使用的内存空间的地址 就是2的32次方
// 指针只需要4位 就可以表示出来所有的内存空间
// 64 并且编译支持64位 8位
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
动态内存分配
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
// malloc memory allocate 内存申请
main()
{
// 接受一个参数 申请多大(byte)的内存空间
int* p = (int*)malloc(sizeof(int)); // 在堆内存里面申请一块可以存放一个int类型数据的内存空间
*p = 4; // 就是往 p 里面存放的地址 表示的那块内存空间里面存放一个int类型的数据 4
printf("*p=%d\n",*p);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
f(int** address){ //address 存放的是q的地址
// 动态的在堆内存里面申请一块空间
int* p ;
p = (int*)malloc(sizeof(int)*3);
*p = 3;
*(p+1) = 4;
*(p+2) = 5 ;
printf("子函数里面 地址%#X\n",p);
*address = p;
// 在子函数里面把p释放掉了
free(p);
}
main()
{
int* q ;
f(&q);
printf("主函数里面 地址%#X\n",q);
printf("*q = %d\n",*(q+0));
printf("*q = %d\n",*(q+1)); // 残留的内存映像
printf("*q = %d\n",*(q+2));
//动态内存分配 程序员可以自己手工的决定一个变量的生命周期
//手工的释放调用内存空间
//不要使用已经回收掉的内存空间里面的数据
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
多级指针
#include <stdio.h>
#include <stdlib.h>
main()
{
int i = 5;
int* p = &i;
int** q = &p;
int*** r = &q;
printf("i=%d\n",***r);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
函数的指针
/*1.定义int (*pf)(int x, int y);
2.赋值 pf = add;
3.引用 pf(3,5);
*/
#include <stdio.h>
#include <stdlib.h>
int add(int x , int y){
return x+y;
}
main()
{
int (*pf) (int x, int y); //定义一个函数的指针的声明 名字叫pf 返回值 int 接受参数两个int
pf = add;
printf("result=%d\n", pf(3,6));
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
结构体
#include <stdio.h>
#include <stdlib.h>
struct Student
{
int age; //4
float score; // 4/
long id; //4
char sex ; //2 vc 6.0 14
};
main()
{
struct Student st={80,55.6f,100010 ,'F'};
struct Student* pst;
pst = &st;
printf("age = %d\n",st.age);
printf("score = %f\n",st.score);
printf("id = %ld\n",st.id);
printf("sex = %c\n",st.sex);
// 结构体的长度
printf("长度 = %d\n",sizeof(st));
//printf("age = %d\n", (*pst).age);
printf("age = %d\n", pst->age);
system("pause"); // 调用windows下系统的命令 让程序暂停执行 方便观察程序的执行结果
}
image.png
联合体
#include <stdio.h>
main( )
{
struct date { int year, month, day; } today;
// 联合体 是定义一块相同的内存空间 存放里面的数据
union { long i; int k; char ii; } mix;
// 联合体的作用就是用来表示一组数据类型 数据的数据类型为这一组中的某一种数据类型
//注意 : 联合体里面的数据内容会相互覆盖
printf("date:%d\n",sizeof(struct date)); //12
printf("mix:%d\n",sizeof(mix));
mix.ii = 'A';
printf("k=%d\n",mix.k);
system("pause");
}
image.png
枚举类型
#include <stdio.h>
typedef int haha;
enum WeekDay
{
Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
};
// c
//
int main(void)
{
haha i = 3;
printf("%d\n",i);
//int day;
enum WeekDay day = Sunday;
printf("%d\n",day);
system("pause");
return 0;
}
image.png