您的位置:首页 > 其它

sizeof strcpy strcat

u010232305 2016-03-28 21:20 10 查看
参考资料:

http://dylanwu.iteye.com/blog/968879

一、sizeof

1、栈中的数组

对于栈中的数组,sizeof给出的会是实际的数组长度,而非指针长度。

2、指向字符串常量的指针

当一个指向数组或常量字符串(堆中,栈中或数据区的数组)的指针变量时,sizeof的结果将会是一个指针变量的长度,比如在32位机下将会是4

3、全局变量

对于全局变量中数组,sizeof的处理结果和在栈中的数组一样,会输出其实际的数组长度,而非一个指针变量的长度。对于全局变量中的指向数组的指针sizeof的处理方式为返回一个指针变量的长度。

4、函数参数

对于函数参数,无论是写成数组形式还是指针形式,sizeof都只会返回一个指针变量的长度。

5、结构体

结构体有些复杂,它存在一个内存对齐机制,记住下面三点原则就没问题了(win32平台下 C编译器):

(1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除;

备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为对齐模数(即数据类型在内存中的存放地址都要是这个对齐模数的整数倍)。

(2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是该成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);

备注:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。

(3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(trailing padding)。

备注:结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。

PS:内存对齐的原因

许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。当一种类型S的对齐模数与另一种类型T的对齐模数的比值是大于1的整数,我们就称类型S的对齐要求比T强(严格),而称T比S弱(宽松)。这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个double类型数据就只需要一次内存操作。否则,我们就可能需要两次内存操作才能完成这个动作,因为数据或许恰好横跨在两个符合对齐要求的8字节内存块上。某些处理器在数据不满足对齐要求的情况下可能会出错,但是Intel的IA32架构的处理器则不管数据是否对齐都能正确工作。不过Intel奉劝大家,如果想提升性能,那么所有的程序数据都应该尽可能地对齐。

ANSI C标准中并没有规定,相邻声明的变量在内存中一定要相邻。为了程序的高效性,内存对齐问题由编译器自行灵活处理,这样导致相邻的变量之间可能会有一些填充字节。对于基本数据类型(int char),他们占用的内存空间在一个确定硬件系统下有个确定的值,所以,接下来我们只是考虑结构体成员内存分配情况。

针对sizeof(结构体)举几个例子:

eg1:

struct{
char a1;
int a2;
}B;

int main()
{
int a;
char b;
cout << "sizeof(int): " << sizeof(a) << endl;
cout << "sizeof(char): " << sizeof(b) << endl;
cout << "sizeof(struct{char int}): " << sizeof(B)<< endl;
return 0;
}


运行结果:



eg2:

struct{
double a1;
int a2;
}B;

int main()
{
int a;
double b;
cout << "sizeof(int): " << sizeof(a) << endl;
cout << "sizeof(double): " << sizeof(b) << endl;
cout << "sizeof(struct{double int}): " << sizeof(B) << endl;
return 0;
}


运行结果:



eg3:

struct{
short a1;
short a2;
char a3;
int a4;
}B;

int main()
{
int a;
short b;
char c;
cout << "sizeof(int): " << sizeof(a) << endl;
cout << "sizeof(short): " << sizeof(b) << endl;
cout << "sizeof(char): " << sizeof(c) << endl;
cout << "sizeof(struct{short short char int}): " << sizeof(B) << endl;
return 0;
}


运行结果:



6、总结例程

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

struct{
short a1;
short a2;
short a3;
}A;
struct{
short a1;
short a2;
char a3;
int a4;
}B;

int main()
{
char* ss1 = "0123456789";//ss1存入栈中,“0123456789”存入字符常量存储区
char ss2[] = "0123456789";//ss2存入了栈中
char ss3[100] = "0123456789";//ss3存入了栈中
int ss4[100];
char q1[] = "abc";
char q2[] = "a\n";
char* q3 = "a\n";
char* str1 = (char*)malloc(100);//开辟了一个堆
void *str2 = (void*)malloc(100);

cout << sizeof(ss1) << endl;//一个指针的32位系统为4 64位系统为8
cout << sizeof(ss2) << endl;//
cout << sizeof(ss3) << endl;//同上
cout << sizeof(ss4) << endl;//同上
cout << sizeof(q1) << endl;//同上
cout << sizeof(q2) <<endl;//同上
cout << sizeof(q3) << endl;//
cout << sizeof(A) << endl;//
cout << sizeof(B) << endl;//
cout << sizeof(str1) << endl;//
cout << sizeof(str2) << endl;//

return 0;
}


运行结果:



二、sizecpy strcat

1、strcpy的使用方法

2、strcat用法

strcat(str1,str2)会先去掉str1的结束符后再把str2接连到str1末尾,这样很符合一个字符串只能有一个结束符的规定。
标签: