c - C胖指针实现失败
问题描述
我最近发现了一个库,它使用胖指针实现了类似 C++ 向量的功能。
我试图在一个简短的程序中复制类似的行为(参见下面的代码)。我可以很好地访问数组元素,但是当我尝试获取元素的数量时,我的程序会打印垃圾。
#include <stdio.h>
#include <stdlib.h>
int main()
{
double * a = NULL;
// the data
double b[] = {1, 2, 3, 5};
a = (int *) malloc(sizeof(int) + sizeof(double *));
a[0] = 4;
a++;
a = b;
// will print 1.0 2.0 3.0 5.0
printf("%lf %lf %lf %lf\n", a[0], a[1], a[2], a[3]);
// prints garbage
printf("%d\n", *((int *) a - 1));
// this will fail
free(((int *) a - 1))
return 0;
}
问题很可能出在代码的指针算术部分,即(int *) a - 1
指向错误的地址,但我不知道为什么会这样。
任何帮助表示赞赏。
解决方案
在数组开头打包长度不是胖指针,而是格式错误的 PASCAL 数组。
int main(fat_pointer);
int main(int argc, char* argv[argc]); // standard signature for main is a fat pointer
胖指针是一个指针和一个索引。索引的数据类型是保证sizeof index <= sizeof(size_t)
. 换句话说,sizeof(int) <= sizeof(size_t)
这是对所有合规托管环境的要求,因为main
要求如此。请注意,这size_t
不是为独立环境定义的。
函数的问题_s
在于它们使用sal.h
Microsoft 允许在声明之前使用变量。
char * strcpy_s(char * restrict dest, rsize_t destsz, char const * restrict src);
// fat pointer form fails
char * strcpy_s(char dest[destsz], rsize_t destsz, char const * src);
胖指针形式失败,因为 destsz 是在后面声明的,所以不能使用。附件 K 很糟糕,因为它在声明之前以胖指针形式使用。看之前在main
哪里argc
声明argv
;这是声明胖指针的正确方法。
#include<stdio.h>
#include<stdlib.h>
void print_vector_double(int len, double d[len])
{
for (int i = 0; i < len; i++)
printf("%lf ", d[i]);
printf("\n");
printf("%d\n", len);
}
int main(int argc, char* argv[argc])
{
// C89 VLA - initialized VLA
double b[] = { 1, 2, 3, 5, };
int b_len = (int)(sizeof b / sizeof b[0]);
print_vector_double(b_len, b);
// C99 VLA - uninitialized VLA
int c_len = b_len;
double c[c_len];
c = b;
print_vector_double(c_len, c);
// Good Old Heap for Dynamic Arrays
int a_len = b_len;
double * a = malloc(a_len * sizeof * a);
double * temp = memcpy(a, b_len * sizeof * b, b);
if (temp != a) exit(EXIT_FAILURE);
print_vector_double(a_len, a);
free(a), a = NULL, a_len = 0;
}
胖指针是您传递给函数的内容。如果您没有将任何内容传递给另一个函数,则没有胖指针。
大提琴无法理解胖指针到底是什么。
推荐阅读
- javascript - 从具有动态模式的嵌套 json 创建一个扁平的可编辑表
- reactjs - 用未知数量的点反应传单矢量图层(多边形)
- c++ - 邮箱进入 SimGrid
- flutter - 颤振:计算 CustomSingleChildLayout 内的小部件大小
- language-agnostic - 如何根据匹配模式合并/连接来自两个数据帧的多个列
- symfony - 根据兄弟FormType的数据动态设置FormType的选项?
- command-line-interface - 如何在 alpine 上使用 cli 工具列出 Vsphere 中的所有 VM?
- np - 用负数映射子集总和
- asp.net - 了解 SignalR-集线器、依赖注入和控制器
- angular - AfterAll TypeError:无法读取未定义的属性“isCompleted” - 角度单元测试