问题描述
我能够做到这一点:
char * months[] = {"empty","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"}; unsigned short int month_index = 4; printf("The %dth month of the year is \"%s\".\n", month_index, months[month_index]);
但是,如果我尝试使用双指针:
But if I try and use a double pointer:
char ** months = {...};
它无法使用excess elements in scalar initializer构建.这到底是什么意思,我将如何使用指向指针的指针初始化以上内容?
It fails to build with a excess elements in scalar initializer. What does that mean exactly, and how would I initialize the above using a pointer to pointers?
推荐答案
类型控制所有内容
char *months[] = {"empty","jan",...};
将月份作为指针数组声明为char,其中初始化程序完成类型,提供数组中的指针数量>(多少?"信息)并初始化每个指针以指向有效字符串的开头.完整的类型为char *[13](由13个指针组成的数组.
Declares months as an array-of-pointers to char where the initializer completes the type providing the number of pointers in the array (the "How many?" information) and initializing each pointer to point to the beginning of a valid character string. The complete type is char *[13] (an array of 13 pointers.
如果您只是想声明:
char *months[];
您的编译器会抛出错误,抱怨months是不完整类型.
You compiler would throw an error complaining that months was in incomplete type.
在声明和初始化months之后,通过操作 C11标准-6.3.2.1其他操作数-左值,数组和函数指示符(p3)在访问时,月份与char**类型兼容,因为第一级间接转换为指针到第一个元素,则导致访问时间为char**个月(以规则中的4个例外为准).
After months has been declared and initialized, then by operation of C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3), on access, months is type-compatible with char** as the first level of indirection is converted to a pointer to the first element, resulting in months being char** on access (subject to the 4 exceptions in the rule).
为什么我不能声明char **months = {"empty","jan",...};开始?
Why Can't I Just Declare char **months = {"empty","jan",...}; To Begin With?
使用 pointer-to-pointer-to-type 完全不涉及数组.声明了多少个指针?虽然使用char *months[]...数组的初始化器 可以完成类型并提供 array 中的元素数量,但是使用char **months时,您只需使用( )指向完全不涉及数组的指针.以下声明的含义:
With a pointer-to-pointer-to-type there is no array involved at all. How many pointers are declared? While with char *months[]... the initializer for the array can complete the type and provide for the number of elements in an array, with char **months, you simply have a (pointer)-to-pointer with NO array involved at all. Meaning following the declarations of:
char **months;
months只是一个未初始化的指针,其中包含一些不确定的地址.任何试图更改不确定的内存位置的内容的尝试都会导致 Undefined Behavior (可能是SegFault). C标准完全没有像 Array 那样提供指针对指针的初始化. C11标准-6.7.9初始化
months is simply an uninitialized pointer holding some indeterminate address. Any attempt to change the content of the indeterminate memory location results in Undefined Behavior (and likely a SegFault). The C-standard simply does not provide for initialization of a pointer-to-pointer as it does for an Array. C11 Standard - 6.7.9 Initialization
该错误虽然有些微妙,但却十分合理.声明时只有一个指针:
The error, while a bit subtle, makes perfect sense. You have a single pointer when you declare:
char **months;
如果您尝试使用初始化列表(例如
If you try to initialize the single pointer with an initializer-list, e.g.
char **months = { "empty", "jan", "feb", ... };
初始化器 ...
您可以通过两种方式来初始化指针到指针的类型. (1)您可以分配所需数量的指针,例如
You have two ways to initialize a pointer-to-pointer-to-type. (1) You can either allocate the number of pointers you need, e.g.
char **months = malloc (13 * sizeof *months); /* allocate 13 pointers */
,然后为一个字符串中的第一个字符分配一个有效地址,或将其分配给13个指针中的每个指针,例如months[0] = "empty"; months[1] = "jan", ...;或
and then allocate for, or assign, a valid address to the first character in a character string to each of the 13-pointers, e.g. months[0] = "empty"; months[1] = "jan", ...; or
(2),您可以分配与指针类型兼容的(单个)对象的有效地址,例如
(2) you can assign the valid address of a (single) object that is type-compatible with your pointer, e.g.
char **my_months = months;
然后您可以使用my_months[0]访问每个单独的字符串,因为指针到指针现在指向有效存储,并且类型完整,以致my_months + 1指向当前字符串之后的下一个字符串.例如:
You can then access each individual string with my_months[0], because the pointer-to-pointer now points to valid storage and the type is complete such that my_months + 1 points to the next string after the current. For example:
#include <stdio.h> int main (void) { char *months[] = { "empty", "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; char **my_months = months; size_t n = sizeof months / sizeof *months; for (size_t i = 0; i < n; i++) printf ("my_months[%2zu] : %s\n", i, my_months[i]); }
使用/输出示例
$ ./bin/my_months my_months[ 0] : empty my_months[ 1] : jan my_months[ 2] : feb my_months[ 3] : mar my_months[ 4] : apr my_months[ 5] : may my_months[ 6] : jun my_months[ 7] : jul my_months[ 8] : aug my_months[ 9] : sep my_months[10] : oct my_months[11] : nov my_months[12] : dec
仔细检查一下,如果还有其他问题,请告诉我.
Look things over and let me know if you have further questions.
这篇关于将指针数组转换为双指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!