问题描述:写一个函数,接受一个整数(假定用int表示),输出该整数的字符串形式。采用如下函数原型:
void itoa ( int val, buf* );
这里假定buf足够大以容纳任何int类型数值的字符串。
这个问题,初看好像没有什么难度。如果是0,就直接输出'0';如果是正数,就通过取模(%)和求商(/)运算可以逐位取得该整数的数字,并把它们放到buf中去;如果是个负数,就先转成正的,然后在最后输出时加入负号。按照这个思路,可以写下如下代码:
void itoa_flawed(int val, char* buf)
{
// deal with special case
if(val == 0)
{
buf[0] = '0';
buf[1] = '\0';
return;
}
bool negative = (val < 0);
int abs_val = negative ? -val : val;
unsigned int char_cnt = 0;
while(abs_val > 0)
{
buf[char_cnt] = abs_val % 10 + '0';
char_cnt ++;
abs_val = abs_val / 10;
}
if(negative) buf[char_cnt++] = '-';
//reverse the string
unsigned int i = 0;
while(i < char_cnt / 2)
{
char temp = buf[i];
buf[i] = buf[char_cnt-i-1];
buf[char_cnt-i-1] = temp;
i++;
}
buf[char_cnt] = '\0';
}
&n ......
问题描述:写一个函数,接受一个整数(假定用int表示),输出该整数的字符串形式。采用如下函数原型:
void itoa ( int val, buf* );
这里假定buf足够大以容纳任何int类型数值的字符串。
这个问题,初看好像没有什么难度。如果是0,就直接输出'0';如果是正数,就通过取模(%)和求商(/)运算可以逐位取得该整数的数字,并把它们放到buf中去;如果是个负数,就先转成正的,然后在最后输出时加入负号。按照这个思路,可以写下如下代码:
void itoa_flawed(int val, char* buf)
{
// deal with special case
if(val == 0)
{
buf[0] = '0';
buf[1] = '\0';
return;
}
bool negative = (val < 0);
int abs_val = negative ? -val : val;
unsigned int char_cnt = 0;
while(abs_val > 0)
{
buf[char_cnt] = abs_val % 10 + '0';
char_cnt ++;
abs_val = abs_val / 10;
}
if(negative) buf[char_cnt++] = '-';
//reverse the string
unsigned int i = 0;
while(i < char_cnt / 2)
{
char temp = buf[i];
buf[i] = buf[char_cnt-i-1];
buf[char_cnt-i-1] = temp;
i++;
}
buf[char_cnt] = '\0';
}
&n ......
第7章 内存管理
欢迎进入内存这片雷区。伟大的Bill Gates 曾经失言:
640K ought to be enough for everybody
— Bill Gates 1981
程序员们经常编写内存管理程序,往往提心吊胆。如果不想触雷,唯一的解决办法就是发现所有潜伏的地雷并且排除它们,躲是躲不了的。本章的内容比一般教科书的要深入得多,读者需细心阅读,做到真正地通晓内存管理。
7.1内存分配方式
内存分配方式有三种:
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
7.2常见的内存错误及其对策
发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。而这些错误大多 ......
第7章 内存管理
欢迎进入内存这片雷区。伟大的Bill Gates 曾经失言:
640K ought to be enough for everybody
— Bill Gates 1981
程序员们经常编写内存管理程序,往往提心吊胆。如果不想触雷,唯一的解决办法就是发现所有潜伏的地雷并且排除它们,躲是躲不了的。本章的内容比一般教科书的要深入得多,读者需细心阅读,做到真正地通晓内存管理。
7.1内存分配方式
内存分配方式有三种:
(1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。
(2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。
7.2常见的内存错误及其对策
发生内存错误是件非常麻烦的事情。编译器不能自动发现这些错误,通常是在程序运行时才能捕捉到。而这些错误大多 ......
時間不等人,在我還未老去之前,想把丟掉的C程式重新再揀起來。
入門,建議(我也是新手)不要看譚大爺的書,對于20世紀學習C語言,c Primer Plus 5th我認為是一個好的選擇。
我的第一個C程式,回想當年,是多麽興奮。。。
#include <stdio.h>
int main()
{
printf("hello yichang\n");
int num;
num=0;
int i;
for (i=1;i<=100;i++)
{
num=num+i;
if(num==5050){
printf("%d=%d\n",i,num);}else{
printf("%d+",i);
}
}
printf("1+2+3...+98+99+100 ,total is: 10进制:%#d,8进制:%#o...“无前缀表示,%d,%o”\n有梦就去做别管天什么时候亮!!!\n",num,num,num,num); //“#”号显示C前缀
return 0;
}
......
一. 何谓可变参数
int printf( const char* format, ...);
这是使用过C语言的人所再熟悉不过的printf函数原型,它的参数中就有固定参数format和可变参数(用”…”表示)。
而我们又可以用各种方式来调用printf,如:
printf("%d",value);
printf("%s",str);
printf("the number is %d ,string is:%s", value, str);
二.实现原理
C语言用宏来处理这些可变参数。这些宏看起来很复杂,其实原理挺简单,就是根据参数入栈的特点从最靠近第一个可变参数的固定参数开始,依次获取每个可变参数的地址。下面我们来分析这些宏。在VC中的stdarg.h头文件中,针对不同平台有不同的宏定义,我们选取X86平台下的宏定义:
typedef char *va_list;
/* 把va_list被定义成char*,这是因为在我们目前所用的PC机上,字符指针类型可以用来存储内存单元地址。
而在有的机器上va_list是被定义成 void* 的 */
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
/* _INTSIZEOF(n)宏是为了考虑那些内存地址需要对齐的系统,从宏的名字来应该是跟sizeof(int)对齐。一般的sizeof(int)=4,也就是参数 ......
1. c语言中的整数类型有char, short, int, long等几种, 下面是C语言对每种数据类型长度的规定:
(a). short和long类型的长度不相同
(b). int类型通常同具体机器的物理字长相同
(c). short通常是16bits, int通常是16bits or 32bits每种编译器可以根据硬件的不同自由确定, 但是short和int必须最少是16bits, 而long类型必须最少是32bits, 并且short必须比int和long类型要短。
2. sizeof() 运算符返回的是一种数据类型中所包含的字节数(bytes), AnsiC规定sizeof(char)必须返回1,当sizeof作用于数组时, 返回的是数组中所有成员所占的字节数(注意并不是数组中成员的个数), 当sizeof()作用于结构体和公用体时,返回的不仅仅是数据成员总的字节数, 还包括编译器为了实现字节对其而填充的那些字节。
---------------------------------------------------------------------------------------------------------------------------------------------
C++数据类型长度问题:
一、字节和字长
字节,八位就是一个字节,是固定概念。字长是指计算机一次能处理的二进制数据的长度,是一个非固定的概念。例如,8位计算机的字长为8,即一个字节, 32位计算机的字长位32,即4个字节,同 ......
1. c语言中的整数类型有char, short, int, long等几种, 下面是C语言对每种数据类型长度的规定:
(a). short和long类型的长度不相同
(b). int类型通常同具体机器的物理字长相同
(c). short通常是16bits, int通常是16bits or 32bits每种编译器可以根据硬件的不同自由确定, 但是short和int必须最少是16bits, 而long类型必须最少是32bits, 并且short必须比int和long类型要短。
2. sizeof() 运算符返回的是一种数据类型中所包含的字节数(bytes), AnsiC规定sizeof(char)必须返回1,当sizeof作用于数组时, 返回的是数组中所有成员所占的字节数(注意并不是数组中成员的个数), 当sizeof()作用于结构体和公用体时,返回的不仅仅是数据成员总的字节数, 还包括编译器为了实现字节对其而填充的那些字节。
---------------------------------------------------------------------------------------------------------------------------------------------
C++数据类型长度问题:
一、字节和字长
字节,八位就是一个字节,是固定概念。字长是指计算机一次能处理的二进制数据的长度,是一个非固定的概念。例如,8位计算机的字长为8,即一个字节, 32位计算机的字长位32,即4个字节,同 ......
mmap是linux下的CreateFileMapping,用来映射并同步文件。
这样的话,比如我自定义一种文件格式,把它写入到文件中,现在想修改其中的值,就可以用这个函数,把文件映射到内存中
然后用操作数组的方式,来进行文件的同步。如果不用这个函数就得:
1、定义一个结构体
2、定义结构体数组
3、读取文件(w+)
4、修改文件
5、写回文件
如果用这个函数,就不需要那么麻烦了:
1、定义结构体
2、定义结构体指针
3、打开文件,将文件句柄传递给mmap进行映射,返回的是结构体数组
4、修改并写回
具体的差异体现在回写上。
贴段代码,例子是《linux程序设计 第三版》中给的。
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
typedef struct
{
int integer;
char string[24];
} RECORD;
#define NRECORDS 100
#define FILENAME ("records.dat")
int main()
{
RECORD record, *mapped;
int i,f;
FILE *fp;
fp = fopen(FILENAME,"w+");
if(!fp)
{
perror("opern file error");
return EXIT_FAILURE;
......
mmap是linux下的CreateFileMapping,用来映射并同步文件。
这样的话,比如我自定义一种文件格式,把它写入到文件中,现在想修改其中的值,就可以用这个函数,把文件映射到内存中
然后用操作数组的方式,来进行文件的同步。如果不用这个函数就得:
1、定义一个结构体
2、定义结构体数组
3、读取文件(w+)
4、修改文件
5、写回文件
如果用这个函数,就不需要那么麻烦了:
1、定义结构体
2、定义结构体指针
3、打开文件,将文件句柄传递给mmap进行映射,返回的是结构体数组
4、修改并写回
具体的差异体现在回写上。
贴段代码,例子是《linux程序设计 第三版》中给的。
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
typedef struct
{
int integer;
char string[24];
} RECORD;
#define NRECORDS 100
#define FILENAME ("records.dat")
int main()
{
RECORD record, *mapped;
int i,f;
FILE *fp;
fp = fopen(FILENAME,"w+");
if(!fp)
{
perror("opern file error");
return EXIT_FAILURE;
......