获取指针的长度(不是sizeoff)

时间:2017-05-10 15:00:43

标签: c pointers

由于某些特殊原因,我需要获得指针的长度(字符)。 如果指针是:

0x2ADF4

它应该返回5, 因为指针中有5个字符。 实际上我希望指针的十六进制表示的长度被转换为整数。  这个数字应该从指针到指针不等。 请注意我不希望总内存占用我的指针(我可以通过sizeoff获得)。

3 个答案:

答案 0 :(得分:4)

您可以将ptr转换为intptr_t类型,然后使用标准数字计数算法:

int main() {
    int counter = 0;
    int* ptr = &counter;
    intptr_t val = (intptr_t)ptr; 

    while ( val > 0 )
    {
        val/=16;
        ++counter;
    }

    printf("%d", counter);

    return 0;
}

答案 1 :(得分:4)

所以你想要你的指针的一些文本表示的长度(谨防术语,你不希望分配的内存区域的大小持有该指针),通常是指针的指针一些virtual address space内存位置(但可能不是)。

您应该注意到sprintf and snprintf都返回写入某个缓冲区的字节数(包括终止零字节),并且它们都接受NULL缓冲区,因此您可以编码:

int ptrtextlen = sprintf(NULL, "%p", ptr);

在你的情况下(ptr为0x2ADF4),它将返回8(因为0x2ADF4需要7个字节,从0开始,x需要4 },以及一个额外的终止零字节)。顺便说一句,请阅读有关sprintf的更多信息(您可以使用它来获取一些前导零,但您可能需要将ptr转换为long或更多可能uintptr_t

(AFAIK,C11标准不保证指针与%p的任何特定文本表示 - 它们是特定于实现的;我正在考虑我的Linux / x86-64桌面)

如果你想要一些空终止字符串的长度(由指向其第一个字符的指针给出)使用strlen

  

我不希望总内存占用我的指针(我可以通过sizeof得到)

这是非常错误的。所有指针都有相同的sizeof(与指向内存的大小无关),在我的Linux / x86-64机器上是8个字节;所以例如

 char buf[32];
 int ptrtextlen = snprintf(buf, sizeof(buf), "%p", ptr);
 printf("ptrtextlen=%d length(buf)=%zd\n", ptrtextlen, strlen(buf));

应该在我的Linux / x86-64桌面上输出ptrtextlen=6 length(buf)=5

int*heaptr = malloc(1024*sizeof(int));
printf("%zd", sizeof(heaptr));

将输出8(不是4096,这是成功调用malloc时给出的内存区域的字节大小,因为sizeof(int)在我的机器上为4)

PS。花几天时间阅读有关C11及其n1570规范的更多内容;看起来你很困惑。阅读C dynamic memory allocation

答案 2 :(得分:-2)

指针的大小取决于机器的体系结构,使得32位系统的指针在内存中为4个字节,而64位系统将其作为内存中的8个字节。这些尺寸在特定系统上不会改变。了解这一点将有助于您设计所需的算法。您的函数或方法应首先检查特定计算机的指针大小。一旦知道了指针的大小,下一步就是检查它是否是小端或大端。一旦您能够确定正在使用哪个字节序,那么您就可以开始设计算法了。在您知道这两个是什么之后,您应该能够将实际的物理地址存储到字符数组中。然后,您可以从中删除所有非重要的前导零,为您留下任何非零的字符,并将它们保存到新的动态字符数组中。我建议使用unsigned char。然后,计算您从原始地址推断出的无符号字符数组中有多少字节。请注意,如果地址是十六进制值,则每2个字符为1个字节。因此,如果结果字符数组有8个值,则有4个字节;但是你想要在长度中返回8而不是以字节为单位返回4。

编辑 - 伪代码

unsigned getAddressLength( unsigned char& address ) {
    // First Check to See if System is 16bit, 32bit, 64bit etc.
    unsigned sizeInBytes = sizeof( address );

    bool isBigEndian;

    // test if Big or Little Endian;
    if ( address is Big ) {
        isBigEndian = true;
    } else {
        isBigEndian = false;
    }

    unsigned char[] addressBytes; // Evert 2 Characters In The Address String is 1 byte of memory.
    if ( isBigEndian ) {
         // Perform Algorithm This Way To Strip Out Non Significant 0s
    } else {
         // Same Thing But For Little Endian
    }

    // After Striping out All Non Significant leading 0s get the size in bytes of this new array

    return (new length of character array);
}