首页 > 解决方案 > 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指向错误的地址,但我不知道为什么会这样。

任何帮助表示赞赏。

标签: cpointers

解决方案


在数组开头打包长度不是胖指针,而是格式错误的 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.hMicrosoft 允许在声明之前使用变量。

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;
}

胖指针是您传递给函数的内容。如果您没有将任何内容传递给另一个函数,则没有胖指针。

大提琴无法理解胖指针到底是什么。


推荐阅读