繁体   English   中英

如何在编译时获取数组中的字符串长度?

[英]How to get string length in the array at compile time?

我的问题与有关,但来自略有不同的站点。

假设我们有相同的数组

const char *data[] = {
    "Str1",
    "Str Two",
    "Long string three",
};

好的,编译器知道数组的长度,我们可以在编译时得到它: sizeof(data)/sizeof(data[0]) 同时编译器知道每个字符串的大小,比如strlen(data[1])的结果实际上在编译时是已知的。 但是strlen是运行时调用, sizeof[i]总是会返回sizeof(char *)值。 有没有办法在没有将每个字符串单独定义为变量的情况下获取每个数组字符串的长度?

更新 2

根据您的要求,我将明确 state 标准中没有任何部分允许您获取常量字符串的长度,除非使用strlen之类的函数。 您将无法创建可以执行您想要的操作的宏。

你写了:

strlen 是运行时调用

它可以是运行时调用或编译时调用,具体取决于编译器的优化级别,到目前为止,还没有其他人提到过。 我非常喜欢让编译器为我完成工作。

$ cat t.c
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[]) {
    char *data[] = {"abc"};
    printf("sl=%ld\n", strlen(data[0]));
}
$ gcc t.c
$ nm a.out
                 U ___stack_chk_fail
                 U ___stack_chk_guard
0000000100008018 d __dyld_private
0000000100000000 T __mh_execute_header
0000000100003f00 T _main
                 U _printf
                 U _strlen
                 U dyld_stub_binder
$ gcc -O1 t.c
$ nm a.out
0000000100008008 d __dyld_private
0000000100000000 T __mh_execute_header
0000000100003f70 T _main
                 U _printf
                 U dyld_stub_binder

更新 1,由 chqrlie 提示。 请参阅 100003f7b 处的说明。 更改该字符串中的字符数将产生一个不同的常量被加载到 esi 寄存器中。

$ objdump --disassemble-symbols=_main a.out

a.out:  file format mach-o 64-bit x86-64


Disassembly of section __TEXT,__text:

0000000100003f70 <_main>:
100003f70: 55                           pushq   %rbp
100003f71: 48 89 e5                     movq    %rsp, %rbp
100003f74: 48 8d 3d 33 00 00 00         leaq    51(%rip), %rdi  # 100003fae <dyld_stub_binder+0x100003fae>
100003f7b: be 03 00 00 00               movl    $3, %esi    #### This is the length of the string constant
100003f80: 31 c0                        xorl    %eax, %eax
100003f82: e8 05 00 00 00               callq   0x100003f8c <dyld_stub_binder+0x100003f8c>
100003f87: 31 c0                        xorl    %eax, %eax
100003f89: 5d                           popq    %rbp
100003f8a: c3                           retq

但即使是运行时调用,也有两件事要记住:

  1. 与您可能对字符串执行的许多其他操作相比,优化的strlen调用的成本非常小。
  2. 您可以通过负责任的保理最大限度地减少调用strlen的频率。

如果您不介意稍微更改data的定义,则可以。

struct Elem
{
  size_t len;
  const char* str;
}

#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)))
#define ELEM(x) ({ ARRAY_SIZE((x)) - 1, ((x)) })

const Elem[] data = {
  ELEM("Str1"),
  ELEM("Str Two"),
  ELEM("Long string three")
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM