c语言笔记

本文深入探讨C语言的const修饰符、类型说明、指针与数组、格式化输入输出及C++的构造函数、智能指针、Lambda表达式等核心概念,覆盖从基本语法到高级特性。

C语言笔记

const修饰符

int const* x; //x值不可变
int const x; //x指针不可变
int const * const x; //x和x都不可变
//int const i 和 const int i 等效。

可以将const变量赋值给非const变量;可用非const变量对const变量初始化赋值。

不可将const变量传递给非const形参;
可将非const变量传递给const形参,

类型说明(typedef)

define与typedef

处理时间分别在预处理和编译,typedef定义了新的数据类型。

#define PINT int *
typedef int *intp_t;
const PINT p; //p可变,*p不可变
const intp_t p; //p不可变,*p可变

指针和数组

指向n个元素数组的指针:

int (*p)[10]; //此时定义了1个指针变量p,指向10元素的数组

指针数组:

int *p[10]; //此时定义了10个指针变量,分别指向整型数。

函数指针

int f(char* cp, int i){return 0;}

struct _st
{
    UINT32 (*function)(INT8 *, UINT32);
} st;
st.function = (UINT32(*)(INT8*, UINT32))f; //强制类型转换

typedef void (*fn_type)(char *, int);
fn_type fun = (fn_type)f;

 

格式化输出

printf("<格式化字符串>", <参数表>)

  1. 格式化规定符:
    %d 十进制有符号整数
    %u 十进制无符号整数
    %f 浮点数
    %s 字符串
    %c 单个字符
    %p 指针的值
    %e 指数形式的浮点数
    %x, %X 无符号以十六进制表示的整数
    %0 无符号以八进制表示的整数
    %g 自动选择合适的表示法
    %ld long整数
    %lf double浮点数
    %3d 输出三位整型数,右对齐。
    %-3d 输出三位整型数,左对齐。
    %03d 输出三位整型数,不足三位左补0。
    %9.2f 输出9位浮点数,小数2位,整数6位。小数位超过宽度按四舍五入,整数位超过则按实际输出。
printf("=%3s=", “hello”); //输出 “=hello=”
printf("=%.3s=", “hello”); //输出 “=hel=”
printf("=%6s=", “hello”); //输出 “= hello=”
printf("=%-6s=", “hello”); //输出 “=hello =”
  1. 一些特殊规定字符
    \n 换行
    \f 清屏并换页
    \r 回车
    \t Tab符
    \xhh 表示一个ASCII码用16进表示,
    其中hh是1到2个16进制数

格式化输入

scanf("<格式化字符串>", <地址表>)

格式化字符串包括:
格式化说明符:与printf基本相同
空白字符:在读操作中略去输入中的一个或多个空白字符
非空白字符:在读入时剔除掉与这个非空白字符相同的字符

说明:
0、输入字符串时,遇到空格即认为输入结束,因此无法输入带空格的字符串;
1、数组名和指针变量名前不用加"&";
2、可限制最大位数:scanf("%10s", p)输入字符数大于10后的字符均被读入下一个读入函数。
3、连续使用多个scanf函数时,由于每个scanf只能用回车完成输入,则每隔一个scanf,就被读入一个回车符(显示出来为空行),为解决此问题,可用fflush()函数。

文件输入输出

一、标准文件函数

FILE *fopen(char *filename, char *type); /*FILE是一个新的数据类型,结构指针。*/

其中第二个参数type的规定:

“r” 打开文字文件只读
“w” 创建文字文件只写
“a” 增补, 如果文件不存在则创建一个
“r+” 打开一个文字文件读/写
“w+” 创建一个文字文件读/写
“a+” 打开或创建一个文件增补
“b” 二进制文件(可以和上面每一项合用)
“t” 文这文件(默认项)

int fclose(FILE *stream); //成功返回0,否则非0

//顺序写:
int fprintf(FILE *stream, char *format, ); //返回实际写入字符数,错误时返回负数
int fputs(char *string, FILE *steam); //写入字符串后不自动换行,成功返回0,否则非0
int fputc(int ch, FILE *steam); //成功返回所写字符,否则返回EOF(-1)

//顺序读:
int fscanf(FILE *stream, char *format, );
char fgets(char *string, int n, FILE *steam); //成功返回string指针,否则空指针
int fgetc(FILE *steam); //成功返回所读字符,否则EOF

//随机读写:
int fseek (FILE *stream, long offset, int fromwhere);

int fread(void *buf, int size, int count, FILE *stream); //读count个字段,每个字段size个字节。
int fwrite(void *buf, int size, int count, FILE *stream);
long ftell(FILE *stream);

int fflush(FILE *stream); //fflush()将缓冲区内容写入文件并清空缓冲区。

feof()和rewind()

二、非标准文件函数

(ANSI C未定义,UNIX和DOS3.0以上系统均支持该类函数)

int open(char *filename, int access); //成功返回非负值,失败返回-1
int close(int handle);

int read(int handle, void *buf, int count);
int write(int handle, void *buf, int count);
int lseek(int handle, long offset, int fromwhere);
long tell(int handle);

其他

预处理符号 # 和 ## 的区别

# 使得后面跟的参数转化为字符串;## 连接前后两个参数(不可放在参数表的最前或最后),但不转化为字符串,多用于生成新的符号名。如:
#define s(a) # a
#define ss(a, b) a_ ## b
char* first_name = s(hello);
char* last_name = “world”;
printf(“%s %s\n”, s(hello), ss(last, name));
//经过宏替换后变为 printf(“%s %s\n”, “hello”, last_name);

变参宏定义

C宏中的变参… …在C宏中称为Variadic Macro,也就是变参宏。比如:

#define myprintf(templt,) fprintf(stderr,templt,VA_ARGS)

或者

#define myprintf(templt,args…) fprintf(stderr,templt,args)

第一个宏中由于没有对变参起名,我们用默认的宏__VA_ARGS__来替代它。

第二个宏中,我们显式地命名变参为args,那么我们在宏定义中就可以用args来代指变参了。
同C语言的stdcall一样,变参必须作为参数表的最后有一项出现。
当上面的宏中我们只能提供第一个参数templt时,C标准要求我们必须写成:myprintf(templt,);的形式。
这时的替换过程为:myprintf(“Error!\n”,);替换为:fprintf(stderr,“Error!\n”,).
这是一个语法错误,不能正常编译。这个问题一般有两个解决方法。
首先,GNU CPP提供的解决方法允许上面的宏调用写成:myprintf(templt);
而它将会被通过替换变成: fprintf(stderr,“Error!\n”,);
很明显,这里仍然会产生编译错误(非本例的某些情况下不会产生编译错误)。

除了这种方式外,c99和GNU CPP都支持下面的宏定义方式:

#define myprintf(templt, ) fprintf(stderr,templt, ##VA_ARGS)

这时,##这个连接符号充当的作用就是当__VAR_ARGS__为空的时候,消除前面的那个逗号。

那么此时的翻译过程如下: myprintf(templt);被转化为: fprintf(stderr,templt);
这样如果templt合法,将不会产生编译错误。

时间处理

time_t time(time_t *tloc); 如果参数为空,则返回1970-01-01 00:00:00到现在经过的秒数

struct tm *localtime(const time_t *timer); tm结构具有根据time_t解析出来的丰富的信息

char *asctime(const struct tm *timeptr); 转换为可打印的字符串

char *ctime(const time_t *clock); 等效于asctime(localtime(clock))

 

程序的windows窗口和DOS窗口

windows下编程,常见的子系统有windows和console,主函数分别为WinMain和main,用gcc(cygwin)编译的程序,默认为console子系统,可以通过-mwindows或–subsystem,windows连接选项来改变为windows子系统,但仍然可以使用main作为主函数(估计是编译器中做了一定的判断和相关操作)。改为windows子系统后,程序的console界面就不显示出来了。或者更简单的办法:用UE打开生成的console子系统的exe文件,将0xDC处的字节0x03(console子系统)修改为0x02(windows子系统)即可(vckbase上描述的是PE头偏移0x3C+子系统在PE中的偏移0x5C,但我用gcc编译出来的exe实际地址是0x80+0x5c)

在JAVA中使用C库 (jni)

https://blog.youkuaiyun.com/songze_lee/article/details/76039875

C++笔记

杂项

函数名前的const和函数名后的const:

函数开头的 const 用来修饰函数的返回值,表示返回值是 const 类型。

函数头部的结尾加上const表示常成员函数,不能修改成员变量的值。

构造函数

拷贝构造函数

T(const T & t);

使用场合:

①. 函数的参数是一个对象,并且是值传递方式

②. 函数的返回值是一个对象,并且是值传递方式

③. 用一个对象初始化另外一个对象。如:

T t2 = t1;
T t3(t1)

拷贝赋值

T & operator = (const T & t)

移动构造函数

T(T && t)

移动赋值

T &operator = (T && t)

 

#include <iostream>

using namespace std;

class T {
public:
    T() {cout << "normal constructor" << endl;}
    T (int i) {cout << "normal constructor from int" << endl;}
    T (T& t) {cout << "copy constructor" << endl;}
    T &operator = (const T &t) {cout << "operator =" << endl;}
};

int main ()
{
    T t;        //默认构造
    T t1 = t;   //拷贝构造
    T t2;       //默认构造
    t2 = t;     //拷贝赋值
    return 0;
}

 

STL

在 STL 中,默认情况下,比较大小是通过<运算符进行的,和>运算符无关。

在 STL 中,对于在未排序的区间上进行的算法,如顺序查找算法 find,查找过程中比较两个元素是否相等用的是==运算符;但是对于在排好序的区间上进行查找、合并等操作的算法(如折半查找算法 binary_search,关联容器自身的成员函数 find)来说,x和y相等是与x<y和y<x同时为假等价的,与==运算符无关。

重载的++运算符,尽量使用前置++,避免使用后置++。(理由)

强制类型转换

static_cast、reinterpret_cast、const_cast 和 dynamic_cast 

http://c.biancheng.net/view/410.html

异常

throw; //继续抛出捕获的异常

异常声明列表

void func() throw (int, double, A, B, C);

C++ 11

智能指针 (c++ 11)

shared_ptr<T> ptr(new T); 

http://c.biancheng.net/view/430.html

Lambda表达式(匿名函数)(c++ 11)

[外部变量访问方式说明符] (参数表) -> 返回值类型
{
   语句块
}

http://c.biancheng.net/view/433.html

auto和decltype关键字(c++ 11)

http://c.biancheng.net/view/438.html

右值引用(c++ 11)

http://c.biancheng.net/view/439.html

转载于:https://www.cnblogs.com/realplay/p/9867523.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值