C语言速成篇
来源:互联网 发布:安徽快三遗漏数据查询 编辑:程序博客网 时间:2024/05/29 07:03
本人最近学习ndk,涉及到C语言,所以写下这篇略显肤浅的笔记……大神请忽略此文……
一、HelloWorld
#include <stdio.h> // 包含标准的输入输出的头文件, 类似java的导包#include <stdlib.h> // 包含标准的库函数main() { // 入口函数 printf("hello World\n"); system("pause"); // 调用系统命令,暂停程序,以便查看运行结果 }
二、数据类型
C语言的数据类型包括基本数据类型、构造类型、指针类型、空类型。其中基本数据类型包括数值类型和字符类型。数值类型又包括整型和浮点类型。基本数据类型如下:
- char 1字节
- short 2字节
- int 4字节
- float 4字节
- long 4字节
- double 8字节
有几个注意事项:
- C语言中没有byte, 可以用char表示
- C语言中没有String类型,可以用字符数组或char类型的指针
- C语言中没有boolean, 可以用整数0表示false, 1表示true
- signed和unsigned: 数据类型修饰符,用来修饰char, short, int, long 如signed int
signed int简称int,signed short简称short,signed long简称long。注意signed char不等于char,这是两种类型了。
main() { long long ago; // sizeof获取某个数据类型的长度 printf("char的长度为:%d\n", sizeof(char)); printf("short的长度为:%d\n", sizeof(short)); printf("int的长度为:%d\n", sizeof(int)); printf("float的长度为:%d\n", sizeof(float)); printf("long的长度为:%d\n", sizeof(long)); // long的长度不会比int短 printf("double的长度为:%d\n", sizeof(double)); printf("long long的长度为:%d\n", sizeof(long long)); printf("signed int的长度为:%d\n", sizeof(signed int)); printf("unsigned int的长度为:%d\n", sizeof(unsigned int)); system("pause"); }
三、输入输出
%hd - short%d - int%ld – long%c - char%f - float%lf – double%u – 无符号数%x – 十六进制输出 %#x- 十六进制输出,并输出0x表示十六进制%o - 八进制输出 %#o - 八进制输出,并输出0表示八进制%s – 字符串
输入:
int count;//scanf会报一个不安全的错误,怎么办呢?//方法一:在引入头文件之前 #define _CRT_SECURE_NO_WARNINGS //宏定义//方法二:使用新函数scanf_fscanf_s("%d",&count);//&表示取变量内存地址,把接收的值赋给countprintf("count=%d\n",count);
输出:
char c = 'a';short s = 1;int i = -1;long l = 255;float f = 3.14;double d = 3.1415926;printf("c = %c\n", c);printf("s = %hd\n", s);printf("i = %d\n", i);printf("l = %ld\n", l);printf("f = %f\n", f);//默认输出6位有效数字printf("f = %.2f\n", f);// .2 输出两位有效数字 printf("d = %lf\n", d); // 默认输出6位有效数字,会四舍五入printf("i = %u\n", i); // 无符号的数 printf("l = %#X\n\n", l); // 十六进制输出 0x
四、指针
指针就是地址,地址就是内存单元的编号;指针变量是存放地址的变量;指针与指针变量是两个概念,但现实中经常把指针变量说成指针。
指针使用中常见错误:
(1)野指针:没有赋值的指针,不能通过*修改对应内存的数据;
(2)数据类型不匹配:比如int类型的指针只能保存int变量的内存地址;
main() { int i = 100; printf("i的内存地址为:%#x\n", &i); // 定义一个指针变量p,用来保存int变量i的内存地址 int* p; // int *p int * p; // 把i的内存地址赋值给指针变量p p = &i; printf("i的内存地址为:%#x\n", p); printf("i= %d\n", i); printf("i= %d\n", *p); // *p表示取p保存的内存地址所存放的值,其实就是i的值 //区分: p 和 &p 和*p printf("%#x\n", p); // i的内存地址 printf("%#x\n", &p); // 指针变量p的内存地址 printf("%d\n", *p); // i的值 system("pause"); }
#include <stdio.h> #include <stdlib.h> main() { int i = 100; int* p = &i; // 一级指针,保存变量的内存地址 int** p2 = &p; // 二级指针,保存一级指针的内存地址 int*** p3 = &p2; // 三级指针,保存二级指针的内存地址 printf("i = %d\n", i); printf("i = %d\n", *p); printf("i = %d\n", **p2); printf("i = %d\n", ***p3); system("pause"); }
指针的应用:
- 交换变量值
#include <stdio.h> #include <stdlib.h> /** 交换两个数的值 */swap1(int i , int j){ // 形参 int temp = i; i = j; j = temp;}swap2(int* p, int* q){ int temp = *p; *p = *q; *q = temp;}main() { int i = 100; int j = 200; // 实数 printf("i = %d\n", i); printf("j = %d\n", j); // swap1(i, j); // 不会交换值 swap2(&i, &j); // 会交换两个数的值 printf("i = %d\n", i); printf("j = %d\n", j); system("pause"); }
- 返回多个值(更改变量值)
#include <stdio.h> #include <stdlib.h> fun(int* p, int* q) { *p =7; *q = 8;}main() { int i =100; int j =200; printf("i = %d\n", i); printf("j = %d\n", j); fun(&i, &j); printf("i = %d\n", i); printf("j = %d\n", j); system("pause"); }
- 主函数中获取子函数变量的内存地址
#include <stdio.h> #include <stdlib.h> fun2(int** q) { int i = 100; printf("i的内存地址为:%#x\n", &i); *q = &i; }main() { int i = 0; int* p = &i; fun2(&p); // 变量还没来得及被回收,但马上被回收了 // printf("i的值为:%d\n", *p); printf("i的内存地址为:%#x\n", p); // 子函数执行完后,局部变量已经被回收 printf("i的值为:%d\n", *p); system("pause"); }
指针与数组:
main() { // char arr[] = {'a', 'b', 'c'}; char arr[] = "Hello"; printf("第1个元素的内存地址: %#x\n", &arr[0]); printf("第2个元素的内存地址: %#x\n", &arr[1]); printf("第3个元素的内存地址: %#x\n", &arr[2]); int arr2[] = {1, 2, 3}; printf("第1个元素的内存地址: %#x\n", &arr2[0]); printf("第2个元素的内存地址: %#x\n", &arr2[1]); printf("第3个元素的内存地址: %#x\n", &arr2[2]); // C语言中的数组越界了,不会报错 printf("第10个元素的值: %d\n\n\n", arr2[9]); // 数组的首地址: 下面三种方式都是一样的 printf("数组的首地址: %#x\n", &arr[0]); printf("数组的首地址: %#x\n", &arr); printf("数组的首地址: %#x\n\n", arr); // 通过指针变量操作数组 char* p = arr; printf("第1个元素的值: %c\n", *p); printf("第2个元素的值: %c\n", *(p+1)); // 往右偏移一个单位, 对于char就是1个字节 printf("第3个元素的值: %c\n\n", *(p+2)); printf("第1个元素的值: %c\n", p[0]); printf("第2个元素的值: %c\n", p[1]); printf("第3个元素的值: %c\n", p[2]); int* q = arr2; printf("第1个元素的值: %d\n", *q); printf("第2个元素的值: %d\n", *(q+1)); // 往右偏移一个单位, 对于int就是4个字节 printf("第3个元素的值: %d\n\n", *(q+2)); // p - q; // 没有意义 system("pause"); }
五、动态分配内存
栈内存:在栈中分配也叫静态分配;栈内存由系统自动那个分配自动回收;空间大小固定,超出会报栈溢出;速度快。
堆内存:在堆中分配也叫动态分配;堆内存需要调用malloc分配,调用free回收;内存有多大,堆就可以有多大;速度相对慢一些。
#include <stdio.h> #include <stdlib.h> #include <malloc.h>main() { int count = 5; // 在堆中创建连续的内存空间 int* p = malloc(sizeof(int) * count); // 对分配出来的内存空间进行赋值 int i = 0; for(; i < count; i++) { // 对每个元素进行赋值 printf("第输入第%d个元素:", (i+1)); scanf_s("%d", &p[i]); // (p+i) } i = 0; // 输出每一个元素 for(; i< count; i++) { printf("第%d个元素为:%d\n", (i+1), p[i]); // *(p+i) } // 释放内存 free(p); printf("第1个元素为:%d\n", p[0]); // 打印第一个元素 system("pause"); }
多次调用malloc这个函数分配的空间是不连续的,若要连续,需要用realloc,用法如下:
.......//省略int* p = malloc(sizeof(int) * count);// 再次分配内存,与上一次分配出来的内存连续// 参1: 上一次分配出来的内存空间的首地址// 参2: 总共要分配多少内存p = realloc(p, sizeof(int) * (count + newCount));printf("p = %#x", p);.......//省略
六、函数指针
函数指针是指向函数的指针变量,本质是一个指针变量,保存函数的内存地址。
#include <stdio.h> #include <stdlib.h> int add(int i , int j) { return i+j;}main() { // 定义一个函数指针,用来保存函数的首地址 int (*pf)(int, int); // 把函数指针进行赋值, 把add函数的首地址赋值给函数指针pf pf = add; // 通过函数指针调用对应的函数 int result = pf(3, 5); printf("result = %d\n", result); system("pause"); }
七、结构体
结构体的长度不是简单地相加,有一个补齐规则:
(1)结构体的长度并不是所有成员长度相加,在编译时长度会进行补齐以方便位移。
(2)结构体长度补齐规则:
结构体成员的偏移量是成员长度的整数倍, 如果不是则补齐
结构体的总长度是所有成员长度的整数倍,如果不是则补齐;
(3)成员的偏移量即:成员的地址与结构体首地址的差值。
定义方式有三种:
- 先定义结构体类型,再定义结构体类型变量
struct Student{ int age; float score; char sex;}main() { struct Student s1; }
- 定义结构体的同时定义结构体类型变量
struct Student2{ int age; float score; char sex;} s1;//也可以再定义如下变量:main() { struct Student s2; }
- 直接定义结构体类型变量
struct { int age; float score; char sex;} s1;
例子:
#include <stdio.h> #include <stdlib.h> void study() { printf("good good study...\n");}struct Student{ int age; // 4 float score; // 4 char sex; // 1 double d; // 8 // 定义函数指针 void (*studyP)();}main() { // 结构体初始化 // 方式1: struct Student s1 = {20, 100, 'f', 0, study}; // 方式2: struct Student s2; s2.age = 25; s2.score = 90; s2.sex = 'm'; s2.studyP = study; // 函数指针赋值 // 访问结构体的成员 printf("s1.age = %d\n", s1.age); printf("s1.score = %f\n", s1.score); printf("s1.sex = %c\n\n", s1.sex); printf("s2.age = %d\n", s2.age); printf("s2.score = %f\n", s2.score); printf("s2.sex = %c\n\n", s2.sex); // 结构体的长度: printf("结构体的长度: s1 = %d\n", sizeof(s1));//24 // 调用函数指针(三种方式) // 方式1: s1.studyP(); // 定义结构体指针变量 struct Student* p; p = &s1; // 方式2: (*p).studyP(); // 方式3 p->studyP(); // 转转换成(*p).studyP() system("pause"); }
八、联合体
当多个数据需要共享内存时可以使用联合体,联合体的成员在赋值时会相互覆盖,因为它们首地址一样。
#include <stdio.h> #include <stdlib.h> union U{ float f; // 4 int i; // 4 char c; // 1}main() { union U u; u.i = 100; u.c = 'a'; printf("u.i = %d\n", u.i); //97 printf("联合体的长度: %d\n", sizeof(u));//4 system("pause"); }
九、关键字typedef
#include <stdio.h> #include <stdlib.h> // 给int起一个别名,叫做jinttypedef int jint;main() { jint aa = 1; printf("aa = %d\n", aa); system("pause"); }
- C语言速成篇
- C语言一夜速成
- C 语言一夜速成!!!
- C语言速成手册(六):其它问题、后记
- C语言速成手册(三):数组、字符串、结构
- 如何用VC++2008速成版编译C语言
- javascript语言速成
- PHP语言速成
- [c/c++]c语言经典之求最大公约数的3中简单方法(速成)
- C#速成(Quick C#)
- Objective-c语法速成
- object c语法速成
- object c语法速成
- C#—SQLite速成
- 小C,速成01
- C语言速成手册(五):其它运算符、文件操作、其它函数
- C语言速成手册(四):指针、动态内存分配、标准输入
- C语言速成手册(二):布尔值、条件判断、循环
- 初识Hadoop,Hadoop是什么?
- 打开路径打开文件
- 七层协议和四层协议
- 动画翻转效果
- 外观模式(Facade Pattern)——随遇而安
- C语言速成篇
- C语言实现简单内存池
- 使用vue框架的时候出现和swiper冲突怎么办
- EXCEL 除重复项
- [笔记分享] [SPI] SPI 协议小结
- yii自带rbac数据表分析
- js模拟双色球
- Python爬虫Cookie的使用
- 用css做一个跳动的心