C/C++学习笔记:基础知识5
来源:互联网 发布:鲁班软件 上市 编辑:程序博客网 时间:2024/05/17 07:51
1 main函数
主函数是一个特殊的函数,不管把它放在代码的什么位置,每个程序的运行都是从主函数开始的。
(1)全局对象的构造函数会在 main 函数之前执行。
main 主函数执行完毕后,可能会再执行一段代码,如下:
//可以使用atexit()函数,注册一个函数//atexit()以栈的方式注册函数,先调用的最后输出,后调用的最先输出#include <stdlib.h>#include <stdio.h>int atexit(void (*function")(void));void fn1( void ), fn2( void ), fn3( void ), fn4( void );int main( void ){ atexit( fn1 ); atexit( fn2 ); atexit( fn3 ); atexit( fn4 ); printf( "This is executed first.\n" );}void fn1(){ printf( "next.\n" );}void fn2(){ printf( "executed " );}void fn3(){ printf( "is " );}void fn4(){ printf( "This " );}//输出结果This is executed first.This is executed next.
此外,全局类的析构函数也是在main()后面执行。
(2)主函数的参数就是输入命令行的参数,主函数不能被其他函数调用
int main(int argc, char *argv[]);int main(int argc, char **argv);int main(void);void main(int argc, char *argv[]);void main(int argc, char **argv);void main(void);
int main( int argc, char *argv[], char *envp[] )
argc表示少命令行参数,第一个就是执行程序名,所argc最少为1。
argv具体参数
envp系统环境变量,“名称=值”形式,以NULL结束
(3)c语言实现都是通过函数mian的返回值来告诉操作系统函数的执行是否成功
0表示程序执行成功,返回非零表示程序执行失败,具体值表示某种具体的出错信息,别的函数不能调用main函数,但系统可以调用main的。
int main(int argc, char **argv, char **env){int i;for(i=0; env[i]; ++i) printf("%s\n", env[i]);return 0;}//其实函数//char *getenv( const char *varname );//的返回值就在main的第三个参数中
2 浮点运算
电脑都是用二进制来表示浮点和整数的,在对一些二进制中无法精确表示的小数进行赋值或读入再输出时, 也就是从十进制转成二进制再转回十进制, 你会观察到数值的不一致. 这是由于编译器二进制/十进制转换例程的精确度引起的。
电脑是用一种浮点的格式来近似的模拟实数的运算, 注意是近似, 不是完全。下溢、误差的累积和其它非常规性是常遇到的麻烦。
不要假设浮点运算结果是精确的, 特别是别假设两个浮点值可以进行等价比较.
浮点数的定义决定它的绝对精确度会随着其代表的值变化, 所以比较两个浮点数的最好方法就要利用一个精确的阈值。
这个阈值和作比较的浮点数值大小有关。
//不要用下面的代码:double a, b;if (a == b) /* 错! *///要用类似下列的方法:#include <math.h>if (fabs(a - b) <= epsilon * fabs(a))//epsilon 被赋为一个选定的值来控制 “接近度”。你也要确定 a 不会为 0//取整数最简单、直接的方法:(int)(x + 0.5);//这个方法对于负数并不正常工作。可以使用一个类似的方法(int)(x < 0 ? x - 0.5 : x + 0.5);
3 可变参数
用 <stdarg.h> 提供的辅助设施,定义可变参数的函数
标准 C 要求用可变参数的函数至少有一个固定参数项, 这样你才可以使用va start()
//把任意个字符串连接起来的函数, 结果存在 malloc 的内存中:#include <stdlib.h> /* 说明 malloc, NULL, size_t */#include <stdarg.h> /* 说明 va_ 相关类型和函数 */#include <string.h> /* 说明 strcat 等 */char *vstrcat(const char *first, ...){size_t len;char *retbuf;va_list argp;char *p;if(first == NULL)return NULL;len = strlen(first);va_start(argp, first);while((p = va_arg(argp, char *)) != NULL)len += strlen(p);va_end(argp);retbuf = malloc(len + 1); /* +1 包含终止符 \0 */if(retbuf == NULL)return NULL; /* 出错 */(void)strcpy(retbuf, first);va_start(argp, first); /* 重新开始扫描 */while((p = va_arg(argp, char *)) != NULL)(void)strcat(retbuf, p);va_end(argp);return retbuf;}//调用如下:char *str = vstrcat("Hello, ", "world!", (char *)NULL);//注意最后一个参数的类型重置; 参见问题 5.2, 15.3。注意调用者要释放返回的存储空间, 那是用 malloc 分配的//error() 函数, 它列印一个出错信息, 在信息前加入字符串 “error: ”和在信息后加入换行符:#include <stdio.h>#include <stdarg.h>void error(const char *fmt, ...){va_list argp;fprintf(stderr, "error: ");va_start(argp, fmt);vfprintf(stderr, fmt, argp);va_end(argp);fprintf(stderr, "\n");}
4 其他
编译有问题时通常的检查要点
(1)未初始化的局部变量
(2)整数上溢, 特别是在一些 16 比特的机器上, 一些中间计算结果可能上溢, 象 a* b / c
(3)未定义的求值顺序
(4)忽略了外部函数的说明, 特别是返回值不是 int 的函数, 或是参数 “缩小” 或可变的函数
(5)复引用空指针, 参见第 5 章。
(6)malloc/free 的不适当使用: 假设 malloc 的内存都被清零、已释放的内存还可用、再次释放已释放内存、malloc 的内部被破坏
(7)指针类常规问题, 参见问题 16.7。
(8)printf() 格式与参数不符, 特别是用 %d 输出 long int
(9)试图分配的内存大小超出一个 unsigned int 类型的范围, 特别是在内存有限的机器上
(10)数组边界问题, 特别是暂时的小缓冲, 也许用于 sprinf() 来构造一个字符串,
(11)错误的假设了 typedef 的映射类型, 特别是 size_t
(12)浮点问题, 参见问题 14.1 和 14.4。
(13)任何你自己认为聪明的在特定机器上的机器代码生成小技巧
判断机器的字节顺序是高字节在前还是低字节在前?
有个使用指针的方法:
int x = 1;if(*(char *)&x == 1) printf("little-endian\n");else printf("big-endian\n");
断言:
assert() 是个定义在 <assert.h> 中的宏, 用来测试断言。一个断言本质上是写下程序员的假设, 如果假设被违反, 那表明有个严重的程序错误。
例如, 一个假设只接受非空指针的函数, 可以写:
assert(p != NULL);
一个失败的断言会中断程序。断言不应该用来捕捉意料中的错误, 例如malloc() 或 fopen() 的失败。
//判断闰年
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
- C/C++学习笔记:基础知识5
- C/C++学习笔记:基础知识
- Objective-c基础知识学习笔记
- Objective-C学习笔记(1) 基础知识
- 【学习笔记四】C语言基础知识复习
- C/C++学习笔记:基础知识2
- C/C++学习笔记:基础知识3
- C/C++学习笔记:基础知识4
- C/C++学习笔记:基础知识6
- C/C++学习笔记:基础知识7
- C/C++学习笔记:基础知识8
- C/C++学习笔记:基础知识9
- C/C++学习笔记:基础知识10
- C/C++学习笔记:基础知识11
- Object-C学习笔记之基础知识一
- C笔记之基础知识
- C/C++基础知识学习
- C#.net基础知识学习
- (Android review)打开Activity返回结果
- 正则表达式匹配包括换行符的所有字符
- Java反射之Class,Constructor,Field
- Am I crazy?
- 页面常用布局模板之二:Stretch
- C/C++学习笔记:基础知识5
- 解决JSP中文乱码问题
- UVA 437 The Tower of Babylon
- 哎呀
- This Android SDK requires Andriod Developer Toolkit version 20.0.0 or above
- 每日算法之四十三:Rotate List (列表旋转k个元素)
- RBL, UBL, Uboot的关系
- 2.设计包含min 函数的栈。3.求子数组的最大和
- hdoj 2099 整除的尾数 水过。。