c语言求px的值的前20项,C语言使用相关汇总二

目录:

13、浮点数与整数比较大小

14、数组

1)定义一个空数组 2)不定长数组(realloc见本章第15)

15、realloc更改己经配置内存空间指令

16、堆、栈、存储区

1)C/C++内存的4个区2)堆和栈中的存储内容

17、#pragma

pack(C程序结构体的内存空间分配原理)

18、typedef和#define的用法与区别

99、总结

--------------------------------------------

--------------------------------------------------------------------------------------------------

13、浮点数与整数比较大小

C语言中浮点数不能直接和整数比较大小,一般方法如下。

1)首先将整数转换为浮点数可以用强制类型转换或赋值给double变量;其次两浮点数相减最后差值取绝对值,检查差值与要求精度差距。

#include "math.h"

int equ_double_int(double a, int c){if(fabs(a-c) 

return(1);

else

return(0);}

2)将整数乘以1.0,比如int

a;

a*1.0编译器认为就是一个浮点数。

3)类型强制转换。

4)float

x=10.001;int

a=10;

if(floor(x+0.0005)>a)

-------------------------------------------------------------------------------------------------------------

14、数组

1)定义一个空数组

输出3,6,9,12......

#include"stdio.h"

void

main()

{

int array[100];//空数组的定义

int

i;

//循环赋值

for(i=0; i<100;

i++)

array[i] = (i + 1) *

3;

//输出

for(i=0; i<100;

i+=)

printf("array[%d] = %d\n", i,

array[i]);

}

-----------------------------------------

2)不定长数组(realloc见本章第15)

①手里有一小段MATLAB程序需要转化成C语言。MATLAB里输入的矩阵可以是任意大小的,但是C语言里的数组一定要是固定大小,对于大小不能确定的数组我想到了用malloc动态申请内存,但是就算用malloc也必须是申请一定大小的存储空间(比如键盘输入的).....但是我的matlab里的向量的长度是根据以前的数据算出来的,在MATLAB里非常容易得到向量长度,一句length(a)就知道向量长度了,MATLAB里不知道长度的向量怎样转化成C语言里的数组并且可以求得其元素个数?

假设数组存的是int型,那么你先申请10个元素int* a = (int*)malloc(sizeof(int)*10);如果又来了一个元素,那么你就可以a=(int *)realloc(a,11*sizeof(int));//更改已经配置的内存空间,动态分配地址然后不够再追加求元素个数int i,n=1;for(i = 0;(a+i)!=NULL;i++);n=i+1;//n就是元素个数

如果你定义的是int型数组比如 int a[10];它的长度就更简单了,n = sizeof(a)/sizeof(int)

②用指针,如:long *UserTime = (long *)malloc(size);//size是你动态需要的大小然后就可以:memset(UserTime,0,size);//初始化为0UserTime[0] = xxx;//象数组那样使用UserTime++;//等于数组下标加一UserTime += xxx;//等于下标加xxxfree(UserTime);//用完释放

③C++程序

#include"stdio.h"#include"malloc.h"intmain(){printf("输入数组大小:\n");intsize;scanf("%d",&size);inti;char*array

= (char*)malloc(size

*sizeof(int));for(i=0;i{printf("请输入数组元素!\n");scanf("%d",&array[i]);printf("array[%d]=%d\n",i,array[i]);}free(array);//malloc申请的内存free来释放,new申请的内存用delete释放return0;}

-------------------------------------------------------------------------------------------------------------

15、realloc更改己经配置内存空间指令

realloc(void *__ptr, size_t __size):更改已经配置的内存空间,即更改由malloc()函数分配的内存空间的大小。

如果将分配的内存减少,realloc仅仅是改变索引的信息。如果是将分配的内存扩大,则有以下情况:1)如果当前内存段后面有需要的内存空间,则直接扩展这段内存空间,realloc()将返回原指针。2)如果当前内存段后面的空闲字节不够,那么就使用堆(由系统分配)中的第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据块释放掉,返回新的内存块位置。3)如果申请失败,将返回NULL,此时,原来的指针仍然有效。

注意:如果调用成功,不管当前内存段后面的空闲空间是否满足要求,都会释放掉原来的指针,重新返回一个指针,虽然返回的

指针有可能和原来的指针一样,即不能再次释放掉原来的指针。

看一下示例代码:

1.#include"stdio.h"

2.#include"stdlib.h"

3.intmain(intargc,char* argv[],char* envp[])

4.{

5.intValueInput;

6.intn;

7.int*numbers1;

8.int*numbers2;

9.numbers1=NULL;

10.

11.if((numbers2=(int*)malloc(5*sizeof(int)))==NULL)//为numbers2在堆中分配内存空间

12.{

13.printf("malloc memory unsuccessful");

14.exit(1);

15.}

16.

17.printf("numbers2 addr: %8X\n",(int)numbers2);

18.

19.for(n=0;n<5;n++)//初始化

20.{

21.*(numbers2+n)=n;

22.//printf("numbers2's data: %d\n",*(numbers2+n));

23.}

24.printf("Enter new size: ");

25.scanf("%d",&ValueInput);

26.//重新分配内存空间,如果分配成功的话,就释放numbers2指针,

27.//但是并没有将numbers2指针赋为NULL,也就是说释放掉的是系统分配的堆空间,

28.//和该指针没有直接的关系,现在仍然可以用numbers2来访问这部分堆空间,但是

29.//现在的堆空间已经不属于该进程的了。

30.numbers1=(int*)realloc(numbers2,(ValueInput+5)*sizeof(int));

31.if(numbers1==NULL)

32.{

33.printf("Error (re)allocating memory");

34.exit(1);

35.}

36.printf("numbers1 addr: %8X\n",(int)numbers1);

37.

41.

42.for(n=0;n<

style="font-family: 宋体; font-size:

12px;">ValueInput;n++)//新数据初始化

43.{

44.*(numbers1+5+n)=n+5;

45.//printf("numbers1' new data: %d\n",*(numbers1+5+n));

46.}

47.printf("\n");

48.free(numbers1);//释放numbers1,此处不需要释放numbers1,因为在realloc()时已经释放

49.numbers1=NULL;

50.//free(numbers2);//不能再次释放

51.return0;

52.}

如果当前内存段后有足够的空间,realloc()返回原来的指针:

1.yugsuo@ubuntu:~/linux/memange$ gcc -g -o realloc realloc_example.c

2.yugsuo@ubuntu:~/linux/memange$ ./realloc

3.numbers2 addr: 8AFC008

4.Enter new size: 10

5.numbers1 addr: 8AFC008

如果当前内存段后没有足够的空间,realloc()返回一个新的内存段的指针:

1.yugsuo@ubuntu:~/linux/memange$ ./realloc

2.numbers2 addr: 9505008

3.Enter new size: 1000000

4.numbers1 addr: B716F008

--------------------------------------------------------------------------------------------------

16、堆、栈、存储区

1)C/C++内存的4个区

在C/C++中,内存分成4个区,他们分别是堆、栈、静态存储区和常量存储区。①栈:就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量,函数参数等。栈就象车站一样,只是一个临时场所。

在函数体中定义的变量通常是在栈上,m是局部变量:在栈中分配,在函数func被调用时才被创建,生命周期为函数func内。m每次调用func都会创建,函数结束就销毁。

②堆:又叫自由存储区,它是在程序执行的过程中动态分配的,它最大的特性就是动态性。由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制(程序员分配),一般一个malloc就要对应一个free。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。如果分配了堆对象,却忘记了释放,就会产生内存泄漏。而如果已释放了对象,却没有将相应的指针置为NULL,该指针就是“悬挂指针”。

用malloc, calloc,

realloc(详见本章15、realloc更改己经配置内存空间指令)等分配内存的函数分配得到的就是在堆上。

③静态存储区:所有的静态变量、全局变量都于静态存储区分配。初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束释放。

在所有函数体外定义的是全局变量,加了static修饰符后不管在哪里都存放在静态存储区,在所有函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。n是全局变量:储存在静态存储区,进入main函数之前就被创建,生命周期为整个源程序。n只创建一次。

④常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然你要通过非正当手段也可以修改,而且方法很多)常量字符串都存放在常量存储区,返回的是常量字符串的首地址。另外函数中的“12345”这样的字符串存放在常量存储区。

char *s中的s是指针,而指针是指向一块内存区域,它指向的内存区域的大小可以随时改变,而且当指针指向常量字符串时,它的内容是不可以被修改的,否则在运行时会报错。char s[]中的s是数组首地址,而数组首地址对应着一块内存区域,其地址和容量在生命期里不会改变,只有数组的内容可以改变。

---------------------------------

2)堆和栈中的存储内容

①栈:在函数调用时,第一个进栈的是主函数中的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

②堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容由程序员安排。

③示例

1 int a = 0; //全局初始化区2 char *p1; //全局未初始化区3 void main()

4 {

5 int b; //栈6 char s[] = "abc"; //栈7 char *p2; //栈8 char *p3 = "12345"; //12345在常量存储区,p3在栈上9 static int c = 0; //静态存储区初始化区10 p1 = (char *)malloc(10); //分配得来10字节的区域 存在堆区11 p2 = (char *)malloc(20); //分配得来20字节的区域 存在堆区12 strcpy(p1, "12345");

13 //12345放在常量存储区,编译器可能会将它与p3所指向的"12345"优化成一块14 }

--------------------------------------------------------------------------------------------------

17、#pragma

pack(C程序结构体的内存空间分配原理)

在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,不仅简化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。

下面以TCP协议首部为例,说明如何定义协议结构。其协议结构定义如下:

#pragma pack(1)

//按照1字节方式进行对齐 设置结构体的边界对齐为1个字节,也就是所有数据在内存中是连续存储的。

struct TCPHEADER

{

shortSrcPort;//16位源端口号

shortDstPort;//16位目的端口号

intSerialNo;//32位序列号

intAckNo;//32位确认号

unsignedcharHaderLen:4;//4位首部长度

unsignedcharReserved1:4;//保留16位中的4位

unsignedcharReserved2:2;//保留16位中的2位

unsignedcharURG:1;

unsignedcharACK:1;

unsignedcharPSH:1;

unsignedcharRST:1;

unsignedcharSYN:1;

unsignedcharFIN:1;

shortWindowSize;//16位窗口大小

shortTcpChkSum;//16位TCP检验和

shortUrgentPointer;//16位紧急指针

};

#pragm apop()

//取消1字节对齐方式

#pragma

pack规定的对齐长度,实际使用的规则是:

结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma

pack指定的数值和这个数据成员自身长度中,比较小的那个进行。 但是,当#pragma

pack的值等于或超过最长数据成员的长度的时候,这个值的大小将不产生任何效果。

而结构整体的对齐,则按照结构体中最大的数据成员进行。

--------------------------------------------------------------------------------------------------

18、typedef和#define的用法与区别

1)#define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不管含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错。例如:#define PI3.1415926

程序中的:area=PI*r*r 会替换为3.1415926*r*r

如果你把#define语句中的数字9 写成字母g 预处理也照样带入。

--------------------------------------2)typedef是在编译时处理的。它在自己的作用域内给一个已经存在的类型一个别名,But you cannot use the

typedef specifier inside a function definition。

--------------------------------------3)typedef int * int_ptr;

与#define int_ptr int *

作用都是用int_ptr代表 int * ,但是二者不同,正如前面所说 ,#define在预处理时进行简单的替换,而typedef不是简单替换

,而是采用如同定义变量的方法那样来声明一种类型。也就是说;

#define int_ptr int *

int_ptr a, b; //相当于int * a, b; 只是简单的宏替换typedef int* int_ptr;

int_ptr a, b; //a, b 都为指向int的指针,typedef为int* 引入了一个新的助记符这也说明了为什么下面观点成立 :

typedef

(int *) pint ;

const

pint p ;//p不可更改,但p指向的内容可更改

pint是一种指针类型const

pint p 就是把指针给锁住了,p不可更改

#define

PINT (int *)

const

PINT p ;//p可更改,但是p指向的内容不可更改。

const

PINT p 是const int * p 锁的是指针p所指的对象。

--------------------------------------

4) #define不是语句,不要在行末加分号,否则会连分号一块置换。typedef后面要加分号。

--------------------------------------------------------------------------------------------------

99、总结

--------------------------------------------------------------------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值