day13
1.C语言本质
操作内存
命令行参数
int main(int argc, char *argv[])
argc: 参数的个数
argv: 参数存放的指针数组
int main(int argc, char *argv[])
{
int i;
for(i = 0; i < argc; i++)
{
printf("%s\n", argv[i]);
}
return 0;
}
2.堆区空间的操作
2.1 malloc
#include <stdlib.h>
void *malloc(size_t size);
功能:开辟堆区空间
参数:
size_t size:开辟空间的大小,单位字节
返回值:
void *: 成功:返回开辟空间的首地址
失败:NULL
注意:
1.malloc 开辟空间是连续的
2.2 free
#include <stdlib.h>
void free(void *ptr);
功能:释放空间
参数:
void *ptr: 释放空间的首地址
注意:
free 不能多次
练习
char *p = (char *)malloc( sizeof(char) * 32);
if( p == NULL)
{
}
char *q = p;
strcpy(p, "123456");
free(p);
p = NULL;
2.申请堆区空间,存放一个字符串,打印出来
char *p = (char *)malloc(sizeof(char) * 32);
if(NULL == p)
{
printf("malloc error\n");
return -1;
}
printf(">:");
gets(p);
printf("str:%s\n", p);
free(p);
p = NULL;
3.结构体
定义一个结构体类型的一般形式为:
struct 结构体名
{
数据类型 成员名1;
数据类型 成员名2;
....
数据类型 成员名n;
};
结构体变量:
存储类型 数据类型 变量名;
访问结构体成员:
变量名 .
指针 ->
eg:
struct student{
char name[32];
int age;
char sex;
};
struct student stu1;
struct student *pstu;
3.1结构体变量的定义
1.无名结构体
struct{
char name[32];
int age;
char sex;
}stu1, stu2;
2.有名结构体
struct student{
char name[32];
int age;
char sex;
}stu1,stu2;
struct student stu3, stu4;
3.取别名
struct student{
char name[32];
int age;
char sex;
};
typedef struct student STU;
typedef struct student* PSTU;
STU stu1, stu2;
PSTU p1, p2;
-------------------------------------------------------
typedef struct student{
char name[32];
int age;
char sex;
}STU, *PSTU;
STU stu1, stu2;
PSTU p1, p2;
4.
typedef struct{
char name[32];
int age;
char sex;
}STU, *PSUT;
STU stu1, stu2;
PSTU p1, p2;
3.2结构体变量初始化和赋值
typedef struct student{
char name[32];
int age;
char sex;
}STU, *PSTU;
1.初始化
STU s1 = {"LiHua", 18, 'x'};
STU s1 = {.name="LiHua", .sex='x', .age=18};
STU s1 = {"LiHua", 18, 'x'};
STU s2 = s1;
2.赋值
STU s1;
strcpy(s1.name, "Lihua");
s1.age = 18;
s1.sex = 'x';
s1 = (STU){"LiHua", 18, 'x'};
s1 = (struct student){.name="LiHua", .sex='x', .age=18};
STU s1 = {"LiHua", 18, 'x'};
STU s2;
s2 = s1;
3.3结构体指针
typedef struct student{
char name[32];
int age;
char sex;
}STU, *PSTU;
1. 结构体指针指向栈区空间的结构体
PSTU p1 = NULL;
STU stu1;
p1 = &stu1;
2. 结构体指针指向堆区空间的结构体
PSTU p1 = NULL;
p1 = (PSTU)malloc(sizeof(STU));
p1 = (struct student *)malloc(sizeof(struct student));
if(p1 == NULL)
{
}
free(p1);
p1 = NULL;
3.4 结构体数组
typedef struct student{
char name[32];
int age;
char sex;
}STU, *PSTU;
struct student stu[10];
STU stu[10];
struct student* stu[10];
PSTU stu[10];
1.初始化
struct student stu[10] = {{"LiHua", 18, 'x'}, {"Zhangn", 50, 'x'}};
3.5结构体的大小
sizeof
遵行字节对齐原则。
默认最大对齐数: 64机 8
32机 4
如果结构体最大成员,没有超过默认最大对齐数, 按最大成员对齐;
超过了默认最大对齐数, 按默认最大对齐数对齐;
#pragma pack(4)
4.typedef
关键字。作用:给数据类型取别名。
typedef int myint;
typedef int* P_int;
typedef int a[5];
typedef int (*p)[5];
typedef int (*P_func)(int, double);
宏定义:
#define 宏名 替换内容
#define P_int int*
P_int p1, p2;
p1:是指针
p2:是整型变量
typedef int * P_int;
P_int p1, p2;
day14
1.共用体
在C语言中,不同数据类型的数据可以使用共同的存储区域,这种数据构造类型称为共用体,简称共用,又称联合体。共用体在定义、说明和使用形式上与结构体相似。两者本质上的不同仅在于使用内存的方式上。
定义一个共用体类型的一般形式为:
union 共用体名
{
成员表列;
};
注意:
1.同一时间,只能使用一个成员(如果有一个新成员被赋值,前面成员的值会被覆盖)
2.共用体的大小有最大成员决定,遵循字节对齐原则
2.枚举 enum
enum 枚举名{
枚举成员1,
枚举成员2,
....
枚举成员n
};
eg:
enum week{Mon, Tue, Wen, Thur, Fri, Sat, Sun};
enum week day = Mon;
注意:
1.实质为批量的宏定义,从第一个开始,赋值为0, 往后一次增加一
2.如果中间的某个成员被赋值,那么依此位置为基准,往后一次增加一
3.枚举变量要求用枚举成员赋值
作用:
1.好看(提高代码的可读性)
3.工具
3.1gcc
Gcc最基本的用法是∶gcc [options] [filenames]
-c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
-g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。
-O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。
-O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
-I 头文件的路径
-L 库路径
-l 链接库名
1.预处理 去注释、头文件展开、宏替换、条件编译等
gcc -E test.c -o test.i
2.编译 检查语法错误,如果没有语法错误,把.c编译生成汇编文件
gcc -S test.i -o test.s
3.汇编 把汇编文件编译生成机器码
gcc -c test.s -o test.o
4.链接 把所有的.o 和相关库链接起来,生成可执行文件
gcc test.o -o test
3.2gdb
首先使用gcc对test.c进行编译,注意一定要加上选项‘-g’
# gcc -g test.c -o test
# gdb test
n 不会进入函数内部,单步执行
s 会进入函数内部,单步执行
4.多文件编程
.c .h
头文件的格式:
#ifndef _FUNC_H
#define _FUNC_H
#endif
作用:防止头文件重复展开
func.c main.c func.h 处于同一文件夹下
gcc func.c main.c -o app
.
├── app
├── inc
│ └── func.h
├── lib
└── src
├── func.c
└── main.c
gcc ./src/func.c ./src/main.c -o app -I ./inc/
5.make
工程管理器,顾名思义,是指管理较多的文件
Make工程管理器也就是个“自动编译管理器”,这里的“自动”是指它能构根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入Makefile文件文件的内容来执行大量的编译工作
Makefile格式
target(目标) : dependency_files(依赖)
<TAB> command
变量定义的两种方式
递归展开方式VAR=var
简单方式 VAR:=var
变量使用$(VAR)
用”$”则用”$$”来表示
类似于编程语言中的宏
预定义变量
AR 库文件维护程序的名称,默认值为ar。AS汇编程序的名称,默认值为as。
CC C编译器的名称,默认值为cc。CPP C预编译器的名称,默认值为$(CC) –E。
CXX C++编译器的名称,默认值为g++。
FC FORTRAN编译器的名称,默认值为f77
RM 文件删除程序的名称,默认值为rm -f
ARFLAGS 库文件维护程序的选项,无默认值。
ASFLAGS 汇编程序的选项,无默认值。
CFLAGS C编译器的选项,无默认值。
CPPFLAGS C预编译的选项,无默认值。
CXXFLAGS C++编译器的选项,无默认值。
FFLAGS FORTRAN编译器的选项,无默认值。
自动变量
$* 不包含扩展名的目标文件名称
$+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$< 第一个依赖文件的名称
$? 所有时间戳比目标文件晚的的依赖文件,并以空格分开
$@ 目标文件的完整名称
$^ 所有不重复的目标依赖文件,以空格分开
$% 如果目标是归档成员,则该变量表示目标的归档成员名称
CC=gcc
CFLAGS= -I ./inc
APP:main.o func.o
$(CC) $+ -o app
main.o:./src/main.c ./inc/func.h
$(CC) -c $< -o main.o $(CFLAGS)
func.o:./src/func.c ./inc/func.h
$(CC) -c $< -o func.o $(CFLAGS)
clean:
rm main.o func.o app
6.条件编译
#if 0
printf("xxxxxxxxxxxxxxxxxxxxxxx\n");
#elif 1
printf("YYYYYYYYYYYYYYYYYY\n");
#elif 0
printf("YYYYYYYYYYYYYYYYYY111111111111111111111\n");
#endif