【问题标题】:Is this possible? [pointer to char array C]这可能吗? [指向 char 数组 C 的指针]
【发布时间】:2011-05-04 14:05:01
【问题描述】:

这可能吗?

size_t calculate(char *s)
{
    // I would like to return 64
}

int main()
{
    char s[64];

    printf("%d", calculate(s));

    return 0;
}

我想写一个函数来计算main()中声明的char数组的大小。

【问题讨论】:

  • 你可以使用“de”sizeof函数。

标签: c arrays pointers char


【解决方案1】:

您的函数calculate(),仅给出了指针参数s,无法计算数组的大小。数组的大小未编码在指针中,也未从指针访问。如果它被设计为将一个以 null 结尾的字符串作为参数,它可以确定该字符串有多长;这就是strlen() 所做的,当然。但是如果它想知道它可以安全地将多少信息复制到数组中,就必须告诉它数组有多大,或者假设有足够的空间。

正如其他人所指出的,sizeof() 运算符可以在数组定义可见的函数中用于获取数组的大小。但是在一个看不到数组定义的函数中,您不能有效地应用sizeof() 运算符。如果数组是一个全局变量,其定义(非声明)在写入calculate() 的范围(可见)内 - 因此不是函数的参数 - 那么calculate() 可以指示大小。

这就是为什么很多很多 C 函数都需要一个指针和一个长度的原因。信息的缺失是为什么 C 有点容易让人误用它并产生“缓冲区溢出”错误的原因,即代码试图将一加仑信息放入品脱罐中。

【讨论】:

    【解决方案2】:

    在静态声明的char[] 上,您可以使用运算符sizeof,在这种情况下将返回64。

    printf("%d", sizeof(s));
    

    在动态声明的char* 上,无法获取已分配内存的大小。

    动态数组是通过malloc和朋友们获得的。所有其他都是静态声明的,您可以在它们上使用sizeof,只要您在声明数组的相同范围内使用它(例如,在您的情况下,使用相同的函数) .

    【讨论】:

    • 您可以将sizeof() 应用于非静态数组定义并获取数组的大小。它适用于静态数组(内部和外部函数)、全局数组、自动数组和 VLA(可变长度数组)。它仅适用于数组的定义(而不是声明)可见的情况 - 并且明显无法使用数组(意思是指针)参数产生有用的答案 - 如问题所示。它不适用于动态分配的数组(使用 malloc() 或亲戚创建)。
    • 好的——你是对的。但是,问这个问题的人会理解你的非标准术语吗?如果您解释它的含义,那么它可以帮助他们理解您的答案。
    【解决方案3】:

    是的,如果s 在其数组的末尾有一个特定字符,这是可能的。例如,您可以有s[63] = 125,并且知道从 0 到 62 的每个其他字符都不会是 125,您可以执行 for 循环,直到找到 125 并返回数组的大小。

    否则,这是不可能的,因为函数参数中的s 只是指向您的数组的指针,因此calculate 中的sizeof(s) 只会返回您的机器指针大小,而不是像预期的那样返回64。

    【讨论】:

      【解决方案4】:

      不幸的是,您无法仅从指针值确定相应数组中有多少元素。您要么需要数组中的某种标记值(例如用于字符串的 0 终止符),要么需要单独跟踪它。

      可以做的是使用sizeof 运算符获取数组中的字节数或元素数:

      char arr[64];
      
      size_t size = sizeof arr;                 // # of bytes in arr
      size_t count = sizeof arr / sizeof *arr;  // # of elements in arr
      

      但是,这仅在arr 是数组类型时才有效;如果你试图在你的函数中这样做

       size_t calculate(char *s)
       {
         return sizeof s;
       }
      

      它将返回指针值的字节大小,而不是相应数组对象的大小。

      【讨论】:

        【解决方案5】:

        没有。 char *xchar x[] 只是创建一个指向内存位置的指针。指针不包含有关内存区域大小的任何信息。

        但是,char *x = "Hello" 占用 6 个字节(包括终止的 null),strlen(x) 将返回 5。这依赖于字符串末尾的 null 字符,strlen 仍然对底层缓冲区一无所知。所以strlen("Hello\000There") 仍然是 5。

        【讨论】:

          【解决方案6】:

          这通常使用 C 中的宏来完成,例如:

          #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
          

          这是否是一个好主意是一个完全不同的问题。

          【讨论】:

          • 只有在静态声明 x 时才有效。对于动态声明的数组,需要将长度保存在单独的变量中。
          • @Rick-Rainer:什么是静态声明的数组?它适用于static 数组、全局数组、auto 数组和 VLA(可变长度数组)。它仅在数组的定义可见的情况下才有效 - 并且信号无法通过数组(意思是指针)参数产生有用的答案 - 如问题所示。它不适用于动态分配的数组(使用malloc() 或亲属创建)。而且(抱歉 Nikolai),宏不是问题中提出的问题的解决方案。
          • 人们只是在早上很紧张:)
          • 投反对票是不公平的。 :) 这个想法对 x 有好处,因为“char x[];”。 @Jonathan Leffler:见上文。有一个很好的解释:“char x[64];” "char *x;"
          猜你喜欢
          • 2021-01-26
          • 2012-03-19
          • 1970-01-01
          • 1970-01-01
          • 2018-04-05
          • 1970-01-01
          • 2016-01-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多