指向2D char数组的指针和指向2D int数组的指针有什么区别?

时间:2016-07-28 06:15:37

标签: c arrays pointers multidimensional-array char-pointer

    #include <stdio.h>

    int main()
    {
        char str[3][15] = {"Pointer to","char","program"};
        char (*pt)[15] = str; // statement A
        char *p = (char *)str; // statement B
        printf("%s\n",p[3]); // statement C  - Seg Fault in this line
        printf("%s\n",p); // working properly displaying "Pointer to"
        printf("%s\n",p+1); // here it is pointing to second element of first array so displaying "ointer to"
        printf("%s\n",pt+1); // printing properly "char" as expected
        int num[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
        int (*nm)[3] = num[1];
        int *n = num;
        printf("n - %d\n",n[10]); // statement D
        printf("nm - %d\n",nm[0][0]);
        return 0;
    }

我的问题:

  1. 请帮助我清楚了解数据存储机制 char数组和int数组的情况

  2. 在上面的程序中我理解指向char数组的时候 指向char的二维数组,如语句A所示 正确显示,但是当它被普通的char指针指向时 并尝试在语句C中打印char它正在获得SegFault, 相反,它应该打印'n'(第一个数组中的第三个数字字符“指针 “)所以有混淆为什么在int数组我正在适当 在语句D中元素n = 11,为什么在这种情况下(语句C)它 没有正确打印。

  3. 如果存储char数组,将如何存储数据 在下面显示的这种形式

  4. char str[3][15] = {{'P','o','i','n','t','e','r',' ','t','o'},
                       {'c','h','a','r'},
                       {'p','r','o','g','r','a','m'}};
    

    如果它像这样存储,那么它应该像语句D中显示的整数指针数组一样工作 请帮我指导一下这个问题,并澄清我在char和int数组存储时遇到的问题。

2 个答案:

答案 0 :(得分:3)

让我们一步一步地查看您的代码。

char str[3][15] = {"Pointer to","char","program"};

在这里,您创建了一个包含15个char的三个数组的数组。并且您正在使用字符串文字初始化每个char数组。如果文字比数组短 - 最后一个元素用零填充,所以它与:

相同
char str[3][15] = {
    {'P', 'o', 'i', 'n', 't', 'e', 'r', ' ', 't', 'o', 0, 0, 0, 0, 0},
    {'c', 'h', 'a', 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {'p', 'r', 'o', 'g', 'r', 'a', 'm', 0, 0, 0, 0, 0, 0, 0, 0}
};

然后

char (*pt)[15] = str; // statement A

在这里,您创建pt作为指向15个char数组的指针,并使用str[0]的地址对其进行初始化,即pt指向第一个{来自char[15]的{​​1}}数组。

下一步

str

不行。据我所知 - 你试图让char *p = (char *)str; // statement B 指向p占用的内存中的第一个char。表达式str的类型为str,即它是一个指向字符数组的指针,而不是指向char (*)[15]的指针(因此你被迫使用强制转换),而且无论如何事实上char确实指向存储str的单元格 - 您应该以更安全的方式使用它:

'P'

char *p = &str[0][0]; // the same as "p = str[0];" 引用了str[0]的第一个元素,即str的类型是十五个str[0]的数组,那么你可以引用第一个char {1}}并将其作为地址 - char,或者只是使用“array”类型的表达式衰减键入“指向第一个数组元素的指针”的事实,这就是&(str[0])[0]也可以工作的原因。

让我们继续

str[0]

此行导致未定义的行为,因为格式说明符要求第二个参数为printf("%s\n",p[3]); // statement C - Seg Fault in this line ,但您传递的是const char *。如果你想打印一个字符 - 那样做:

char

然后

printf("%c\n", p[3]); // prints "n"

这些工作得很好,因为第二个参数的类型是正确的,我们知道字符串是以nul结尾的。

    printf("%s\n",p); // working properly displaying "Pointer to"
    printf("%s\n",p+1); // here it is pointing to second element of first array so displaying "ointer to"

坦率地说 - 这是不正确的,因为printf("%s\n",pt+1); // printing properly "char" as expected 是“指向pt + 1数组的指针”,但你应该传递“指向char的指针”。它应该改写为:

char

但它似乎有效,因为无论类型不兼容,两个指针都指向同一位置。

关于printf("%s\n",*(pt+1)); // or pt[1] 的下一部分。

int

以下是两个错误:int num[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; int (*nm)[3] = num[1]; int *n = num; 不应该使用nm进行初始化,因为它们具有不兼容的类型:“指向三个数组的num[1]”与“四个数组{{ 1}} /指向int的指针(由于腐朽)。并且int无法使用int进行初始化,因为它们也具有不兼容的类型。根据我对你想要的东西的猜测,它应该以下一个方式看待:

n

最后一个:

num

取消引用也是正确的并且也传递了参数,但请记住,指针的初始化不正确。

希望,我已经涵盖了你所有的问题。

答案 1 :(得分:2)

您的段错是由于您将错误的类型传递给printf。

p[3]您正在引用指向矩阵char第一行的第4 str的指针。与*(p+3)

相同

如果你想打印第3个字符,你应该

printf("%c\n",p[3]);

如果要打印第一个C-String(矩阵的第0行),您必须:

printf("%s\n",&p[3]);

因为%s需要char *

如果您为命令添加(至少对于gcc,-Wall选项,编译器将向您显示一个好的有用警告:

test.c:8:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
         printf("%s\n",p[3]); // statement C  - Seg Fault in this line

关于问题3,您必须注意正确的存储是:

char str[3][15] = {{'P','o','i','n','t','e','r',' ','t','o','\0'},
                   {'c','h','a','r','\0'},
                   {'p','r','o','g','r','a','m','\0'}};

由于C-String以空值终止,因此,例如,字符串"Pointer to"将占用11个字符

最后一件事是关于int指针。它运行良好,因为%d格式说明符需要int值,而不是地址。所以写道:

printf("n - %d\n",n[10]);

完全正确,因为n[10]取消引用num矩阵的第11个元素,这意味着第3行的第3个元素。与*(n+10)

相同