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++容器会更安全、更方便。