定义字符串数组
我想定义一个这样的字符串数组:
#define sup (const char**) ("string1", "string2")
但是当我尝试打印第一个字符串时它失败:
printf("The string: %s\n",sup[0]);
如何以正确的方式执行它?
I would like to define an array of string like that:
#define sup (const char**) ("string1", "string2")
but it fails when I try to print the first string:
printf("The string: %s\n",sup[0]);
how to do it in the proper way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我建议不要完全使用宏来执行此操作,但是如果您真的对代码中发生的情况感兴趣,而不是实际应该如何解决这个问题,那么这里有一个解释。
代码中有一个简单的问题,还有一个更晦涩的问题。非常简单的是,声明数组时不使用括号,而是使用大括号:
不太简单的问题是数组不是指针。大括号初始值设定项可用于初始化两个
const char*
的数组,但这与const char**
不同。如果将代码更改为:它应该可以工作。
以前的版本到底发生了什么?好吧,编译器正在查看指针的声明(好吧,转换为指针)和初始值设定项。假设您想用第一个元素初始化指针(不兼容的指针,但强制转换是显式的...如果您强制强制转换,您必须知道自己想要什么),然后忽略余。基本上编译器会将您的代码翻译为 [*]:
这会在运行时造成严重破坏。有趣的是,如果您使用了适当的变量,然后用它初始化了指针,它就会起作用,因为虽然数组不是指针(我坚持认为,请记住这一点)数组可以衰减为指针:
[*] 那里有一些手摇...编译器翻译代码,一旦由预处理器插入到使用宏的位置,但翻译相当于我写的,如果你要编辑手动宏。
I would advice against doing this with macros altogether, but if you are really interested in what is going on with the code --more than in how this should actually be tackled, here is an explanation.
There is a simple issue in the code, and a more obscure one. The very simple is that to declare an array you don't use parenthesis but rather curly braces:
The less simple issue is that arrays are not pointers. The curly brace initializer can be used to initialize an array of two
const char*
, but that is not the same as aconst char**
. If you change the code to:It should work.
What is going on under the hood with the previous version? Well, the compiler is seeing the declaration of a pointer (well, casting to a pointer) and the initializer. It is assuming that you want to initialize the pointer with the first element (incompatible pointer, but the cast is explicit... you must know what you want if you forced the cast), and then ignore the remainder. Basically the compiler translates your code to [*]:
And that will cause havoc at runtime. It is interesting to note that if you had used a proper variable and then initialized the pointer with it, it would have worked, because while arrays are not pointers (I insist, keep that in mind) arrays do decay into pointers:
[*] There's a bit of handwaving there... the compiler translates the code, once inserted at the place of use of the macro by the preprocessor, but the translation is equivalent to what I wrote if you were to edit the macro manually.
我认为执行这种预处理器技巧,尤其是对于数组,并不是一个好主意。相反,您应该拥有一个真正的全局字符串表,如下所示:
在
.c
文件之一中,并将其extern
声明放在标头中,以便在此类字符串所在的位置包含该标头需要:(第一个 const 是为了避免修改每个字符串文字 - 即 UB -,第二个是为了避免替换存储在
sup
中的指针;如果你想允许最后一个操作,删除第二个 const)另一种方法是直接在标头中将
sup
定义为static
全局变量(即使用内部链接);我以前见过用整数常量完成此操作,以确保编译器在每个翻译单元中立即知道它们(因此它可以将它们作为生成的程序集中的立即值),但我不认为使用字符串指针可以显着提高性能。I think that doing this kind of preprocessor tricks, especially with arrays, isn't such a good idea. You should instead have a real global string table, like this:
in one of the
.c
files, and put itsextern
declaration in a header to be included wherever such strings are needed:(the first
const
is to avoid modifications to each string literal - which is UB -, the second to avoid replacing the pointers stored insup
; if you want to allow this last action, remove the secondconst
)An alternative approach would be to define
sup
directly in the header as astatic
global variable (i.e. with internal linkage); I've seen this done before with integer constants to make sure they are immediately known to the compiler in every translation unit (so it can put them as immediate values in the generated assembly), but I don't think that with string pointers it can give any significant performance boost.我有一个所有项目都通用的标题。
代码如下:
克劳德
I have a header that is common to all my projects.
The code looks like:
Claude