C语言 C 双字符指针声明和初始化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4832082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C double character pointer declaration and initialization
提问by vascop
I always though that declaring
我总是虽然那声明
char *c = "line";
was the same as
是一样的
char c[] = "line";
and so I did
所以我做了
char **choices = { "New Game", "Continue Game", "Exit" };
Which gives me an incompatible pointer type, where
这给了我一个不兼容的指针类型,其中
char *choices[] = { "New Game", "Continue Game", "Exit" };
doesn't. Any help on understanding this?
没有。对理解这一点有帮助吗?
采纳答案by Wes Hardaker
Well, they're not the same. It's just easier for most people to think of them as being the same so everyone starts to think that way until they run into a problem like the above :-)
嗯,他们不一样。大多数人更容易认为它们是相同的,所以每个人都开始这样想,直到遇到上述问题:-)
I was going to write something long and winded, but then I figured... Someone else must have done this already. And they have. This is a pretty good explanation:
我打算写一些冗长而啰嗦的东西,但后来我想......其他人肯定已经这样做了。他们有。这是一个很好的解释:
http://www.lysator.liu.se/c/c-faq/c-2.html
http://www.lysator.liu.se/c/c-faq/c-2.html
The easiest way to think about it is that when you do something like:
考虑它的最简单方法是,当您执行以下操作时:
char *foo = "something";
You're really doing something like:
你真的在做这样的事情:
char randomblob[] = "something"; char *foo = randomblob;
Now... that's not really an accurate picture (though I'm not a compiler expert). It at least lets you think about things in a slightly more correct fashion.
现在......这不是一个准确的图片(尽管我不是编译器专家)。它至少可以让你以稍微更正确的方式思考事情。
So, back to your problem, if Iunderstand things right (which is never guaranteed), you can't do your example line #3 in C. You're right that someone could write a compiler that would do the right thing here, but gcc doesn't. The 4th example, however, does the "right thing" and gives you "an array of pointers that are each pointing to a const char array themselves".
所以,回到你的问题,如果我理解正确(这永远无法保证),你就不能用 C 来做你的示例第 3 行。你是对的,有人可以编写一个编译器来做正确的事情,但 gcc 没有。然而,第四个示例做了“正确的事情”,并为您提供“一个指针数组,每个指针都指向一个 const char 数组本身”。
I once ran across a web page that would translate a complex C type into English. That was probably in the early 90s though but I bet if you google enough it would give you a more accurate wording description than the one I just whipped up.
我曾经遇到过一个可以将复杂的 C 类型翻译成英文的网页。那可能是在 90 年代初,但我敢打赌,如果你用足够多的 google 搜索,它会给你一个比我刚刚提出的更准确的措辞描述。
回答by zwol
char *c = "line";
is notthe same as
是不一样的
char c[] = "line";
it's really the same as
这真的是一样的
static char hidden_C0[] = "line";
char *c = hidden_C0;
except that the variable hidden_C0is not directly accessible. But you'll see it if you dump out generated assembly language (it will usually have a name that isn't a valid C identifier, like .LC0). And in your array-of-string-constants example, the same thing is going on:
除了变量hidden_C0不能直接访问。但是,如果您将生成的汇编语言转储出来,您就会看到它(它的名称通常不是有效的 C 标识符,例如.LC0)。在你的字符串常量数组示例中,同样的事情正在发生:
char *choices[] = { "New Game", "Continue Game", "Exit" };
becomes
变成
char hidden_C0[] = "New Game";
char hidden_C1[] = "Continue Game";
char hidden_C2[] = "Exit";
char *choices[] = { hidden_C0, hidden_C1, hidden_C2 };
Now, this is a special case behavior that is available onlyfor string constants. You cannot write
现在,这是一种仅适用于字符串常量的特殊情况行为。你不能写
int *numbers = { 1, 2, 3 };
you must write
你必须写
int numbers[] = { 1, 2, 3 };
and that's why you can't write
这就是为什么你不能写
char **choices = { "a", "b", "c" };
either.
任何一个。
(Your confusion is a special case of the common misconception that arrays are "the same as" pointers in C. They are not. Arrays are arrays. Variables with array types suffer type decayto a pointer type when they are used(in almost every context), but not when they are defined.)
(你的混乱是常见的误解的一种特殊情况,数组是“相同”,在指针C.它们不是。数组是数组。与数组类型变量遭受型衰减到指针类型的,当他们使用(几乎在每一个上下文),但不是在定义时。)
回答by Martin Babacaev
It's ok, just write
没关系,随便写
char **choices = (char *[]){ "New Game", "Continue Game", "Exit" };
char **choices = (char *[]){ "New Game", "Continue Game", "Exit" };
However, choicescan be used only for linear addressing. For example:
但是,choices只能用于线性寻址。例如:
printf ("%s", &(*choices)[0]);outputs: New Gameprintf ("%s", &(*choices)[1]);outputs: ew Gameprintf ("%s", &(*choices)[9]);outputs: Continue Game
printf ("%s", &(*choices)[0]);产出:New Gameprintf ("%s", &(*choices)[1]);产出:ew Gameprintf ("%s", &(*choices)[9]);产出:Continue Game
So it's not a joke, it's a valid initialization. Just another kind of usage.
所以这不是开玩笑,这是一个有效的初始化。只是另一种用法。
You can also find a very close example here, explaining Compound Literalsnotion.
你也可以在这里找到一个非常接近的例子,解释复合文字的概念。
回答by John Bode
Online C standard (draft n1256):
在线 C 标准(草案n1256):
6.7.8 Initialization
...
11 The initializer for a scalarshall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion); the same type constraints and conversions as for simple assignment apply, taking the type of the scalar to be the unqualified version of its declared type.
...
16 Otherwise, the initializer for an object that has aggregate or union typeshall be a brace enclosed list of initializersfor the elements or named members.
6.7.8 初始化
...
11标量的初始化器应该是一个单独的表达式,可选地用大括号括起来。对象的初始值是表达式的初始值(转换后);与简单赋值相同的类型约束和转换适用,将标量的类型作为其声明类型的非限定版本。
...
16 否则,具有聚合或联合类型的对象的初始值设定项应为元素或命名成员的初始值设定项的花括号括起来的列表。
Emphasis added.
加了重点。
char **is a scalar type, not an aggregate, and so is not compatible with the initializer {"New Game", "Continue Game", "Exit"}. By contrast, char *[]is an aggregate (array) type.
char **是标量类型,而不是聚合,因此与初始化程序不兼容{"New Game", "Continue Game", "Exit"}。相比之下,char *[]是聚合(数组)类型。
Similarly, you couldn't write something like
同样,你不能写类似的东西
int *foo = {1, 2, 3};
because int *isn't an array type.
因为int *不是数组类型。
Your understanding of
你的理解
char *c = "line";
and
和
char c[] = "line";
is slightly off; they are notthe same. The first form copies the addressof the string literal to the pointer value c. The second form copies the contentsof the array expression "line"to the buffer designated by c.
稍微偏离;它们不一样。第一种形式将字符串文字的地址复制到指针值c。第二种形式将数组表达式的内容复制"line"到由 指定的缓冲区c。

