写给开发者的C语言快速入门指北

数据类型

C 语言是一个有类型的语言,使用变量必须定义确定类型。

整数:char, short, int, long, long long, bool

浮点数:float, double, long double

指针

自定义类型

数据类型的不同

在64位机器上:

整数和浮点数 在内存中的形式都是以二进制的形式存在的,但是整数是真实的二进制数字 可以直接拿来运算,而浮点数是一种编码方式,不能直接运算。通常来说CPU上专门有一个硬件来处理浮点数运算。

sizeof

这个方法可以返回某个类型或者某个变量在内存中所占据的字节数

sizeof(int);

int a = 0;

sizeof(a);

整数

int 的特殊意义

int 和 long 的长度取决于编译器和CPU,通常的意义是表示 "一个字" 的长度。

什么叫一个字?

CPU和内存读取数据模型:

CPU [register] RAM

CPU中的寄存器通过总线和内存进行数据读写,现在的CPU的寄存器通常这个大小是 32bit 或者 64bit,这个大小就是一个字的长度,通常就代表 int 的长度。

内部的表达

在计算机中任何数据都是二进制数据,这个数据是什么取决与我们怎么看它。

1个字节可以表达的数范围:

因为char刚好就是一个字节,我们就拿char来实验一下:

因为一个字节,只能表达 256 个数字,那么 char 的表示数的范围是 (0 ~ 255) 还是可以表示负数呢?

char c = -1;

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

c=-1

测试代码可以看出 char 是可以表示负数的。

那么负数怎么表示呢?对应的二进制又是怎样的呢?

我们这样这样想 -1 + 1 = 0,那么:

????????

这样看就很明显了:

由于 超出了 1个字节的范围,所以溢出了就变成了

所以虽然内存中的数据都是

,但是当被当成原码看的时候是

255

,当成补码看的时候就是

-1

signed & unsigned

signed, unsigned 数据类型的修饰符,只能修饰 整数类型的数据,表示是否带符号,也就是不用补码来表示负数了。

8进制 16进制

int i = 012; // 八进制

int j = 0x12; // 十六机制

printf("i=0%o,j=%x\n", i, j);

浮点数

精度误差

float f = 1.123f;

float ff = 2.123f;

float sum = f + ff;

if (sum == 3.246f) {

printf("相等\n");

} else {

printf("不相等 sum=%.10f, sum=%f\n", sum, sum);

}

不相等 sum=3.2459998131, sum=3.246000

浮点数是不准确,有效位数是有限的,所以在处理钱的问题上,不要使用小数点来表示角分,而是转换成最小单位来计算,比如: 1.23元 = 123分,这样转换成整数计算就不会又误差了。

指针

指针是什么? 指针就是一个内存地址,代表的就是一块内存空间。

// 定义一个 int类型的变量 i 值为5

int i = 5;

// &i 中的 &为取地址符,可以得到 i 的地址,%x 为十六进制输出

printf("i的地址 %p\n",&i);

关于怎么快速学C/C++游戏编程,有什么方法,这个问题,想必大家都已经心中有数了,打算深入了解这个行业的朋友,可以加下小编的C/C++游戏编程学习群:626+871+916,邀请码(往事)不管你是小白还是大牛,小编我都欢迎,不定期分享干货,包括小编自己整理的一份2018最新的C/C++资料和0基础入门教程,欢迎初学和进阶中的小伙伴。

每天晚上20:00我都会开直播给大家分享C/C++游戏编程学习知识和路线方法,群里会不定期更新最新的教程和学习方法(进群送2018C/C++游戏编程学习教程),大家都是学习C/C++的,或是转行,或是大学生,还有工作中想提升自己能力的前端党,如果你是正在学习C/C++的小伙伴可以加入学习。最后祝所有程序员都能够走上人生巅峰,让代码将梦想照进现实,非常适合新手学习,有不懂的问题可以随时问我,工作不忙的时候希望可以给大家解惑。

// 指针变量 定义一个int* 类型的变量p

int* p;

// 把 i 的地址给 p,现在 p 就存放的 i 的地址

p = &i;

printf("i=%d\n",i);

// *p --> 当指针变量前面有*的时候,表示取这个指针变量所存放的地址里面对应的数据

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

指针占多少字节

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)); // --> 4

printf("double 类型指针变量的长度为 %d\n",sizeof(dp)); // --> 4

printf("float 类型指针变量的长度为 %d\n",sizeof(fp)); // --> 4

printf("char 类型指针变量的长度为 %d\n",sizeof(cp)); // --> 4

数组

数组变量是特殊的指针

无需用 & 取地址

int a[10]; int *p = a;

但是数组的单元表达的是变量,所以是需要用 & 取地址

*a == &a[0]

[]

可以对数组做,也可以对指针做。

p[0]; a[0];

*

也可以对数组做

*a = 0;

数组变量是一个 const 的指针,所以不能被再次赋值,只能初始化。

int b[] = a;

// int b[] === int * const b

指针运算

// 指针的运算和数组都是紧密关联的

char* pChar = &arr[2];

printf("pChar的内存地址:%#X,对于的值为:%c\n", pChar, *(pChar));

printf("pChar + 1 的内存地址:%#X,对于的值为:%c\n", pChar + 1, *(pChar + 1));

// pChar的内存地址:0X28FF22,对于的值为:c

// pChar + 1 的内存地址:0X28FF23,对于的值为:d

// 指针的运算 按照 约定好的数据类型, 偏移相对应的内存空间的大小 !

printf("dist=%c\n", &arr[0] - &arr[2]); // dist=2

// 指针减法 返回的值是距离,并不是返回整数相减的结果

指针类型转换

int* p = &i;

void* q = (void*) p;

函数指针

void print(char const * str) {

printf("%s\n", str);

}

void sayHi(void (* p)(char const * str)) {

p("hi2");

}

sayHi(print);

指针的运用

需要传入较大的数据时用作参数:传数组

对数组的操作

函数返回值不止一个结果的时候

需要用函数来修改不止一个变量:swap

动态申请内存

函数指针相当于java的回调

动态内存分配

#include

// 申请 n个int 大小内存,失败返回 0

int* p = (int*) malloc(n * sizeof(int));

// 回收

free(p);

字符串

声明字符串的三种方式

char c[] = {'H', 'e', 'l', 'l', 'o', '\0'};

printf("%s\n", c);

char c2[6] = {'H', 'e', 'l', 'l', 'o'};

printf("%s\n", c2);

char* str = "Hello World!";

printf("%s\n", str);

字符串数组

char s[][] = {"Hello", "Wrold"};

char *ss[] = {"Hello", "Wrold"};

字符串操作

#include

在标准函数库

string.h

里面有关于 string 处理相关的函数库。

具体方法查找:http://www.runoob.com/cprogramming/c-standard-library-string-h.html

结构类型

枚举

enum Type {

Open,

Close

};

enum Type t = Open;

结构体

struct Position {

int x;

int y;

};

结构体的内存大小为所有成员的大小之和

结构体初始化

struct Position p = ;

struct Position q;

q.x = 2;

q.y = 2;

结构体指针

struct Position* p = &q;

(*p).x = 1;

C的

操作符,其实就是指针取值的简写。

结构体运算

p = (struct Position) ; // 相当于 p.x = 1; p.y = 2;

p1 = p2 // 相当于 p1.x = p2.x; p1.y = p2.y

联合体

union Value {

int x;

float y;

char z;

double q;

};

union Value v;

v.x = 1;

v.z = 'A';

v.y = 0.1;

v.q = 0.2;

printf("%zu\n", sizeof(union Value));

联合体的大小,会存在内存对齐的情况,其内存大小等于成员中最大的那个属性的长度,并且因为联合体内的成员是共用内存的,所以只会安全的保存一个值。

1, 0.000000, , 0.000000

65, 0.000000, A, 0.000000

8

别名

typedef int Age;

typedef int* AgeP;

struct Man {

char* name;

};

typedef struct Man Student, *StudentP;

Age a = 1;

printf("%d\n", a);

AgeP p = &a;

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

Student student;

student.name = "Jack";

printf("%s\n", student.name);

StudentP sp = &student;

printf("%s\n", sp->name);

1

1

Jack

Jack

给结构体取别名,可以让结构体的使用更加接近于Java。

宏定义

#define value

下面这个是 标准 C header 的宏定义,为了解决头文件的导入死循环

#ifndef __X__HEADER__

#define __X__HEADER__

void hello();

#endif

在C99之前,C语言没有

const

关键字,所以定义常量通常也是用宏定义

#define PI 3.14159

编译器处理宏定义其实就是最原始的文本替换。

double x = 2 * PI;

double x = 2 * 3.14159;

带参数的宏

#define cube(x) ((x)*(x)*(x))

printf("%d\n", cube(2)); // 8

end

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180404A15XJK00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券