9、内存操作

  在实际项目设计中,内存操作随处可见,本文这里就重点将内存相关的操作符进行讲解和区分。

1、sizeof的用法

  sizeof一般有以下两种用法:

第一种用法:

sizeof(type_name);//sizeof(类型名)

类型名称包括基本类型,也包括构造类型,如;

sizeof(int)、sizeof(U16)、sizeof(MATH_CUBE_ST)

第二种用法:

sizeof(var_obj_name);//sizeof(变量对象名称

如:

int val;
u32 u32len;
MATH_CUBE_ST stCube;
sizeof(val)      ; sizeof(u32len);sizeof(stCube);

在实际编程中,这两种方法都是可以的,但是一般建议用第二张种方法,以memset来举例,memset用来给指定地址的内存段指定相同的值,通常用来初始化变量,一般用法如下:

MATH_CUBE_ST stCube;
memset(&stCube,0,sizeof(MATH_CUBE_ST));
//将变量stCube全部清零

这样写没有问题,但是每个人写程序时,后面都会用到复制粘贴,英雌我们复制时还要先去找定义行,然后进行复制,之后还要在找函数进行复制粘贴,如果两者距离很长的话,这样做明显是浪费时间且容易出错的,这是,第二种方法的好处就体现出来了,即:

memset(&stCube,0,sizeof(stCube));

这样问题就可以避免了。

2、sizeof的几个特例

  1)、使用sizeof计算数组的大小及元素的个数

    sizeof是在编译时进行计算的,因此可以将sizeof当作常量来对待,使用sizeof可以方便的计算数组所占用的内存大小,也可以计算元素的个数,在计算元素个数是,需要使用除法,示例如下:

/**********************************************************
*        内容:测试sizeof函数计算数组大小
*        说明:无
*        日期:2017.11.1
*        版本:v1.0
************************************************************/
#include <stdio.h>
#include <string.h>

unsigned int au32val[] = { 1,2,3,4,5 };
int main()
{
    //输出数组au32val占用的字节数,4*5=20
    printf("array  length  is  %d
    ", sizeof(au32val));
    //输出数组au32val的元素个数,5
    printf("array element is  %d
", sizeof(au32val) / sizeof(unsigned int));
    return;

}

输出结果如下:

2)、使用sizeof计算新参数组

    看如下示例:

/**********************************************************
*        内容:使用sizeof计算新参数组
*        说明:无
*        日期:2017.11.1
*        版本:v1.0
************************************************************/
#include <stdio.h>
#include <string.h>

int main(char abstract[3])
{
    printf("para len is %d
", sizeof(abstract));
    return;
}

 

这里的结果并不是3,而是4,这里函数参数acStr已经不再是数组了,而是蜕变为了指针,相当于char *acStr,这里是因为数组是传“址”的,调用者只需将实参的地址传过去即可,所以acStr为指针类型(char*),程序结果输出也就是4;

(这里也引出了一个编程中的习惯,一般情况下是不要使用数组作为函数的参数,而是使用指针,如果要再想直到数组的长度,还需要添加一个长度的形参过来。

3)、字符串指针常量和数组字符串中的sizeof

  先看示例如下:

/**********************************************************
*        内容:字符串指针常量和数组字符串中的sizeof
*        说明:无
*        日期:2017.11.1
*        版本:v1.0
************************************************************/
#include <stdio.h>
#include <string.h>

int main()
{
    char* pcpointStr = "123456789";
    char acArrayStr[] = "123456789";
    //输出字符串指针长度
    printf("sizeof(pcpointStr)=%d
", sizeof(pcpointStr));
    //输出字符串指针指向内容的长度,结果为1
    printf("sizeof(*pcpointStr)=%d
", sizeof(*pcpointStr));
    //输出数组的长度,记过为10,系统自动加结束符
    printf("sizeof(acArrayStr)=%d
", sizeof(acArrayStr));
    //输出指针指向的变量长度,结果为1
    printf("sizeof(*acArrayStr)=%d
", sizeof(*acArrayStr));
    return;
}

 

  通过上述示例可以看出指针和数组使用sizeof的区别,出现这样的区别的原因是,sizeof是在编译器直接计算出来的,其次是因为sizeof是计算的内存的大小,字符串指针的类型就是字符串指针类型,所以不管字符串的长度是多少,指针类型的长度都是4个字节,而数组字符串在sizeof下认为是数组类型,而数组类型编译时已经分配了大小,所以返回的为实际大小。

  因此,无论是获取字符串指针指向内容还是字符串数组中的字符串长度,都应该用库函数strlen,而不是用sizeof;

2、memset和memcpy

1)、memset   

  在之前讲解sizeof时,我们已经用到过memset函数,这里将对其进行详细讲解和示例分析。其函数原型如下所示:

void *memset(void *dest, int  c, size_t  counter);

memset函数的作用是将缓存设定为一个专门的字符,对照函数原型,就是将已经开辟内存空间dest的首count个字节的值设定为c。

示例如下:

/**********************************************************
*        内容:测试memset函数
*        说明:无
*        日期:2017.11.1
*        版本:v1.0
************************************************************/
#include <stdio.h>
#include <string.h>

int main()
{
    char TestStr[] = "AAAAAAAAAAAAA";
    printf("The original string is :%s
", TestStr);
    memset(TestStr, 'C', 3);//将TestStr的前三个字符替换成C
    printf("the change string is :%s
", TestStr);
    return 0;
}

结果为:

2)memcpy

   函数原型如下

void *memcpy(void *dest,const    void  *src,    size_t count);

 memcpy函数的作用是在缓存之间复制字符,对照函数原型,memcpy即用来复制src所指向的内存内容的前count个字节到dest所指的内存地址上。

示例如下:

/**********************************************************
*        内容:测试memcpy函数
*        说明:无
*        日期:2017.11.1
*        版本:v1.0
************************************************************/
#include <stdio.h>
#include <string.h>
typedef signed char INT8;//重定义数据类型
typedef signed int INT32;


int main()
{
    char szTestStr[100] = "AAAAAAAAAAAAA";
    char szCopyStr[100] = "HELOWORLD";
    printf("The original string is :%s
", szTestStr);
    memcpy(szTestStr, szCopyStr+2, 3);//将TestStr的前三个字符替换成从szCopy第3个字符开始三个字符
    printf("the change string is :%s
", szTestStr);
    return 0;
}

 

值得注意的是:src与dest所指向的内容不能叠加,函数返回值为指向dest的指针。

在实际项目中,两者经常同时使用,即先用memset初始化某数组或结构体,然后用memcpy将内容复制到被初始化的变量中。

char szStringContent[1024] = { 0 };
......
memset(szStringContent, 0x00, sizeof(szStringContent));
memcpy(szStringContent, "li", strlen("li"));
......

 

原文地址:https://www.cnblogs.com/noticeable/p/7843274.html