C胖指针实现失败

时间:2018-08-14 15:16:33

标签: c pointers

最近我发现了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指向错误的地址,但我不知道为什么是这种情况。

感谢您的帮助。

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,其中argcargv之前被声明;这是声明胖指针的正确方法。

#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无法理解真正的胖指针。