C语言方法学习 std::vector<double> 转化double[]或double * 原创

memset方法

memset 方法是一个在C和C++中广泛使用的库函数,用于将某一块内存中的全部字节设置为指定的值。这个函数通常用于内存空间的初始化或清零操作。以下是关于 memset 方法的详细解释:

函数原型
在C语言中,memset 函数的原型定义在 <string.h> 头文件中;在C++中,则定义在 或 <string.h>(这取决于编译器和平台)中。函数原型如下:

c

void *memset(void *s, int c, size_t n);

参数说明
s:指向要填充的内存块的指针。
c:要被设置的值。需要注意的是,虽然参数类型为 int,但 memset 函数实际上只使用 c 的低8位(即一个字节)。
n:要被设置该值的字节数。
返回值
memset 函数返回一个指向 s 的指针,即原始内存块的指针。

使用方法
初始化数组:可以将数组的所有元素初始化为同一个值。例如,将一个字符数组的所有元素初始化为0或某个字符。
c

char str[100];  
memset(str, 0, sizeof(str)); // 将str数组的所有元素初始化为0  
char chArray[100];  
memset(chArray, 'A', sizeof(chArray)); // 将chArray数组的所有元素初始化为'A'
清空结构体:对于结构体变量,memset 可以用来将其所有成员初始化为0(或-1,但需要注意字节表示)。这对于包含指针的结构体需要谨慎使用,因为将指针成员初始化为0通常是安全的,但可能不是所有成员都适合这样做。
c
typedef struct {  
    char name[20];  
    int age;  
} Person;  
 
Person p;  
memset(&p, 0, sizeof(Person)); // 将p的所有成员初始化为0

注意事项:
memset 是按字节设置内存的,因此对于非字符类型(如 int、float 等)的数组,如果设置的值不是0或-1(在二进制表示中所有字节都相同),则可能不会得到预期的结果。
当使用 memset 对结构体或数组进行初始化时,需要确保不会覆盖任何不应该被修改的内存区域(例如,结构体中的指针成员可能不应该被设置为0,除非这是你的意图)。
对于动态分配的内存,使用 sizeof 运算符时需要特别小心。如果指针变量是通过 malloc、calloc 或 realloc 等函数分配的,那么 sizeof 运算符作用于该指针变量时得到的是指针本身的大小(通常是4或8字节),而不是它所指向的内存块的大小。因此,在这种情况下,应该使用在分配时记录的大小或通过其他方式计算要设置的字节数。
示例
c

#include <stdio.h>  
#include <string.h>  
  
int main() {  
    int array[4];  
    memset(array, 0, sizeof(array)); // 将array的所有元素初始化为0  
  
    for (int i = 0; i < 4; i++) {  
        printf("%d ", array[i]); // 输出: 0 0 0 0  
    }  
  
    return 0;  
}

在这个示例中,memset 函数被用来将一个整型数组的所有元素初始化为0。由于整型数组的每个元素占用多个字节(通常是4字节),但 memset 是按字节设置的,因此这里使用0作为填充值是安全的,因为0的二进制表示在所有字节位置上都是0。然而,如果尝试将数组元素初始化为非0且非-1的整数值,则可能会得到意想不到的结果。

calloc

calloc 是C和C++语言中用于动态内存分配的一个函数,它可以在内存的动态存储区中分配指定数量的连续空间,并自动将分配的内存初始化为零。以下是关于 calloc 函数的详细解释:

一、函数原型
在C语言中,calloc 函数的原型定义在 <stdlib.h> 头文件中(部分旧系统可能也支持 <malloc.h>,但 <stdlib.h> 是更标准的选择)。其原型如下:

c
void *calloc(size_t num, size_t size);
二、功能描述
calloc 函数用于在内存的动态存储区中分配 num 个长度为 size 的连续空间。分配的内存块中的每个字节都会被初始化为0。如果分配成功,函数返回一个指向分配的内存块的起始地址的指针;如果分配失败(例如,由于内存不足),则返回NULL。

三、参数说明
num:指定要分配的元素数量。
size:指定每个元素的大小(以字节为单位)。
四、返回值
成功时,返回一个指向分配的内存块的起始地址的指针。
失败时,返回NULL。
五、与 malloc 的区别
内存初始化:calloc 分配的内存会自动初始化为零,而 malloc 分配的内存则不进行初始化,其内容是不确定的。
参数个数:calloc 需要两个参数(元素数量和每个元素的大小),而 malloc 只需要一个参数(要分配的内存块的总大小)。
效率:如果只需要分配内存而不需要初始化,malloc 通常比 calloc 更高效。
六、使用注意事项
类型转换:由于 calloc 返回的是 void* 类型的指针,如果要将它赋给特定类型的指针变量,需要进行适当的类型转换。
内存释放:使用完分配的内存后,应该使用 free 函数释放它,以避免内存泄漏。
错误检查:在调用 calloc 后,应该检查返回值是否为NULL,以判断内存分配是否成功。
七、示例代码
以下是一个使用 calloc 函数的简单示例:

c
#include <stdio.h>
#include <stdlib.h>

int main() {
int *array = (int *)calloc(10, sizeof(int)); // 分配一个包含10个整数的数组,并初始化为0
if (array == NULL) {
// 处理内存分配失败的情况
printf(“Memory allocation failed!\n”);
return 1;
}

// 使用array...  

// 释放内存  
free(array);  

return 0;  

}
在这个示例中,我们使用 calloc 函数分配了一个包含10个整数的数组,并检查了内存分配是否成功。然后,我们可以安全地使用这个数组,并在不再需要时释放它。

代码规范之错误处理

定义错误
/**
 Error codes returned.
 */
typedef enum DWG_ERROR
{
  DWG_NOERR = 0,
  /* sorted by severity */
  DWG_ERR_WRONGCRC         = 1,
  DWG_ERR_NOTYETSUPPORTED  = 1 << 1, /* 2 */
  DWG_ERR_UNHANDLEDCLASS   = 1 << 2, /* 4 */
  DWG_ERR_INVALIDTYPE      = 1 << 3, /* 8 */
  DWG_ERR_INVALIDHANDLE    = 1 << 4, /* 16 */
  DWG_ERR_INVALIDEED       = 1 << 5, /* 32 */
  DWG_ERR_VALUEOUTOFBOUNDS = 1 << 6, /* 64 */
  /* -------- critical errors ------- */
  DWG_ERR_CLASSESNOTFOUND  = 1 << 7, /* 128 */
  DWG_ERR_SECTIONNOTFOUND  = 1 << 8, /* 256 */
  DWG_ERR_PAGENOTFOUND     = 1 << 9, /* 512 */
  DWG_ERR_INTERNALERROR    = 1 << 10,/* 1024 */
  DWG_ERR_INVALIDDWG       = 1 << 11,/* 2048 */
  DWG_ERR_IOERROR          = 1 << 12,/* 4096 */
  DWG_ERR_OUTOFMEM         = 1 << 13,/* 8192 */

} Dwg_Error;

fread

错误枚举使用

EXPORT int
dat_read_file (Bit_Chain *restrict dat, FILE *restrict fp,
               const char *restrict filename)
{
  size_t size;
  if (!dat->size && fp)
    {
      struct_stat_t attrib;
      int fd = fileno (fp);
      if (fd >= 0 && !fstat (fd, &attrib))
        dat->size = attrib.st_size;
    }
  dat->chain = (unsigned char *)calloc (1, dat->size + 1);
  if (!dat->chain)
    {
      loglevel = dat->opts & DWG_OPTS_LOGLEVEL;
      LOG_ERROR ("Not enough memory.\n")
      fclose (fp);
      dat->fh = NULL;
      return DWG_ERR_OUTOFMEM;
    }

  size = fread (dat->chain, sizeof (char), dat->size, fp);
  if (size != dat->size)
    {
      loglevel = dat->opts & DWG_OPTS_LOGLEVEL;
      LOG_ERROR ("Could not read file (%" PRIuSIZE " out of %" PRIuSIZE
                 "): %s\n",
                 size, dat->size, filename)
      fclose (fp);
      free (dat->chain);
      dat->chain = NULL;
      dat->fh = NULL;
      dat->size = 0;
      return DWG_ERR_IOERROR;
    }
  // ensure zero-termination for strstr, strtol, ...
  dat->chain[dat->size] = '\0';
  return 0;
}

c++ std::vector 转化double[]或double *

在C++中,将std::vector转换为double[](即C风格的数组)并不是直接支持的,因为std::vector是动态数组,而C风格的数组在大小上是固定的,并且它们的生命周期通常与它们被声明的块的生命周期相同。然而,你可以通过几种方式来实现类似的效果。

方法1:使用vector的data()成员函数
如果你的目标仅仅是访问vector内部的数据(例如,将其传递给需要double参数的函数),你可以直接使用std::vector::data()成员函数。这个函数返回一个指向vector内部数据的指针(double),但请注意,这个指针仅在vector的生命周期内有效。

cpp

#include <vector>  
#include <iostream>  
  
void processArray(double* array, size_t size) {  
    for (size_t i = 0; i < size; ++i) {  
        std::cout << array[i] << " ";  
    }  
    std::cout << std::endl;  
}  
  
int main() {  
    std::vector<double> vec = {1.0, 2.0, 3.0, 4.0, 5.0};  
    processArray(vec.data(), vec.size());  
    return 0;  
}

方法2:复制数据到C风格的数组中
如果你确实需要一个C风格的数组,并且想要控制其生命周期,你需要手动复制vector中的数据到一个新的数组中。

cpp

#include <vector>  
#include <iostream>  
  
void processArray(double* array, size_t size) {  
    // 使用数组...  
    for (size_t i = 0; i < size; ++i) {  
        std::cout << array[i] << " ";  
    }  
    std::cout << std::endl;  
  
    // 记得在适当的时候释放数组(如果它是动态分配的)  
    // delete[] array; // 注意:在这个例子中,我们不应该这样做,因为array是指向栈内存的指针  
}  
  
int main() {  
    std::vector<double> vec = {1.0, 2.0, 3.0, 4.0, 5.0};  
  
    // 为C风格的数组分配内存(注意:这里我们直接在栈上分配,因此不需要delete)  
    double array[vec.size()];  
  
    // 复制数据  
    for (size_t i = 0; i < vec.size(); ++i) {  
        array[i] = vec[i];  
    }  
  
    // 使用数组  
    processArray(array, vec.size());  
  
    // 注意:在这个例子中,array是一个栈分配的数组,不需要手动释放  
    return 0;  
}

注意:在上面的第二个例子中,为了简化说明,我在栈上直接分配了一个固定大小的数组。然而,这种方法限制了数组的大小(它必须是编译时常量),并且不适用于需要动态确定数组大小的情况。在需要动态数组大小的场景中,你可能需要使用new来动态分配内存(并记得在不再需要时使用delete[]来释放它),或者使用智能指针(如std::unique_ptr<double[]>)来管理内存。但是,在大多数情况下,如果可能的话,使用std::vector或其他现代C++容器会更安全、更方便。

posted @ 2024-07-12 13:39  一点灯  阅读(0)  评论(0编辑  收藏  举报  来源