最近我发现了library,它使用胖指针实现了类似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
指向错误的地址,但我不知道为什么是这种情况。
感谢您的帮助。
答案 0 :(得分:0)
在数组开头打包长度不是胖指针,而是格式错误的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
函数的问题在于它们使用Microsoft的sal.h
,从而允许在声明之前使用变量。
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;
}
胖指针是您传递给函数的内容。如果您没有将任何内容传递给另一个函数,则没有胖指针。
Cello无法理解真正的胖指针。