类型
![](http://upload-images.jianshu.io/upload_images/20766503-c104d94f143aa2dc.png)
extern 外部变量声明
左值和右值
左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
常量
整数常量
85 /* 十进制 */
0213 /* 八进制 */
0x4b /* 十六进制 */
30 /* 整数 */
30u /* 无符号整数 */
30l /* 长整数 */
30ul /* 无符号长整数 */
浮点常量
3.14159 /* 合法的 */
314159E-5L /* 合法的 */
字符常量
常用的转义常量
![](http://upload-images.jianshu.io/upload_images/20766503-8374083e2fa8be4d.png)
字符串常量
"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
//这三种字符串是等价的,注意使用\换行,使用空格连接
定义常量
#define
const type variable = value;
存储类
static extern
运算符
算术运算符
关系运算符
逻辑运算符
![](http://upload-images.jianshu.io/upload_images/20766503-6fcc935cc2eb6069.png)
位运算符
![](http://upload-images.jianshu.io/upload_images/20766503-ea3f1b81bd8de424.png)
![](http://upload-images.jianshu.io/upload_images/20766503-96090f0f3724ffbe.png)
![](http://upload-images.jianshu.io/upload_images/20766503-bdf398d7d8718a05.png)
![](http://upload-images.jianshu.io/upload_images/20766503-37920b3d92037e95.png)
函数传参
![](http://upload-images.jianshu.io/upload_images/20766503-e2664f6d783c1041.png)
数组
多维数组
type name[size1][size2]...[sizeN];
传递数组给函数
void myFunction(int *param);
void myFunction(int param[10]);
void myFunction(int param[]);
指针
指针的算术运算
指针的每一次递增,它其实会指向下一个元素的存储单元。
指针的每一次递减,它都会指向前一个元素的存储单元。
指针在递增和递减时跳跃的字节数取决于指针所指向变量数据类型长度,比如 int 就是 4 个字节。
函数指针
typedef int (fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型
int ( p)(int, int) = max;
回调函数
#include <stdlib.h>
#include <stdio.h>
// 回调函数
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
for (size_t i=0; i<arraySize; i++)
array[i] = getNextValue();
}
// 获取随机值
int getNextRandomValue(void)
{
return rand();
}
int main(void)
{
int myarray[10];
populate_array(myarray, 10, getNextRandomValue);
for(int i = 0; i < 10; i++) {
printf("%d ", myarray[i]);
}
printf("\n");
return 0;
}
字符串
char greeting[] = "Hello";
等价于
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
结构体
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct
{
int a;
char b;
double c;
} s1;
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{
int a;
char b;
double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;
//也可以用typedef创建新类型
typedef struct
{
int a;
char b;
double c;
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;
//此结构体的声明包含了其他的结构体
struct COMPLEX
{
char string[100];
struct SIMPLE a;
};
//此结构体的声明包含了指向自己类型的指针
struct NODE
{
char string[100];
struct NODE *next_node;
};
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book = {"C 语言", "RUNOOB", "编程语言", 123456};
#include <stdio.h>
#include <string.h>
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
};
int main( )
{
struct Books Book1; /* 声明 Book1,类型为 Books */
struct Books Book2; /* 声明 Book2,类型为 Books */
/* Book1 详述 */
strcpy( Book1.title, "C Programming");
strcpy( Book1.author, "Nuha Ali");
strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* Book2 详述 */
strcpy( Book2.title, "Telecom Billing");
strcpy( Book2.author, "Zara Ali");
strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* 输出 Book1 信息 */
printf( "Book 1 title : %s\n", Book1.title);
printf( "Book 1 author : %s\n", Book1.author);
printf( "Book 1 subject : %s\n", Book1.subject);
printf( "Book 1 book_id : %d\n", Book1.book_id);
/* 输出 Book2 信息 */
printf( "Book 2 title : %s\n", Book2.title);
printf( "Book 2 author : %s\n", Book2.author);
printf( "Book 2 subject : %s\n", Book2.subject);
printf( "Book 2 book_id : %d\n", Book2.book_id);
return 0;
}
位域
https://www.runoob.com/cprogramming/c-structures.html
struct bs{
int a:8;
int b:2;
int c:6;
}data;
struct packed_struct {
unsigned int f1:1;
unsigned int f2:1;
unsigned int f3:1;
unsigned int f4:1;
unsigned int type:4;
unsigned int my_int:9;
} pack;
struct bs{
unsigned a:4;
unsigned :4; /* 空域 */
unsigned b:4; /* 从下一单元开始存放 */
unsigned c:4
};
struct k{
int a:1;
int :2; /* 该 2 位不能使用 */
int b:3;
int c:2;
};
共用体
共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。共用体占用的内存应足够存储共用体中最大的成员
union Data
{
int i;
float f;
char str[20];
} data;
typedef
C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。
- typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
- typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。
输入输出
printf
scanf
getchar() 从屏幕读取一个字符
putchar() 向屏幕输出一个字符
char *gets(char *s) 函数从 stdin 读取一行到 s 所指向的缓冲区,直到一个终止符或 EOF。
int puts(const char *s) 函数把字符串 s 和一个尾随的换行符写入到 stdout
文件读写
fopen() rwab+
fclose()
fputc
fputs
fgetc
fgets
fscanf
fread()
fwrite()
预编辑器
![](http://upload-images.jianshu.io/upload_images/20766503-d07fdc1db2edec3a.png)
![](http://upload-images.jianshu.io/upload_images/20766503-b5e0503a536dcac8.png)
#include <stdio.h>
#define message_for(a, b) \
printf(#a " and " #b ": We love you!\n")
int main(void)
{
message_for(Carole, Debra);
return 0;
}
#define square(x) ((x) * (x))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
C 可变参数
#include <stdio.h>
#include <stdarg.h>
double average(int num,...)
{
va_list valist;
double sum = 0.0;
int i;
/* 为 num 个参数初始化 valist */
va_start(valist, num);
/* 访问所有赋给 valist 的参数 */
for (i = 0; i < num; i++)
{
sum += va_arg(valist, int);
}
/* 清理为 valist 保留的内存 */
va_end(valist);
return sum/num;
}
int main()
{
printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}
内存管理
![](http://upload-images.jianshu.io/upload_images/20766503-b42702270eff3167.png)
命令行参数
#include <stdio.h>
int main( int argc, char *argv[] )
{
if( argc == 2 )
{
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 )
{
printf("Too many arguments supplied.\n");
}
else
{
printf("One argument expected.\n");
}
}
stddef.h
offset的用法
#include <stddef.h>
#include <stdio.h>
struct address {
char name[50];
char street[50];
int phone;
};
int main()
{
printf("address 结构中的 name 偏移 = %d 字节。\n",
offsetof(struct address, name));
printf("address 结构中的 street 偏移 = %d 字节。\n",
offsetof(struct address, street));
printf("address 结构中的 phone 偏移 = %d 字节。\n",
offsetof(struct address, phone));
return(0);
}