二维数组作为指向字符数组的指针

tob*_*kll 3 c arrays pointers

我正在使用 C 中的一些代码,并且我试图理解指针和数组之间的关系。您可能知道,当我想制作数组时,可以这样做:

char * arr = "abc";
Run Code Online (Sandbox Code Playgroud)

或者

char arr[] = {'a','b', 'c'};
Run Code Online (Sandbox Code Playgroud)

但是当我想做二维数组时。必须这样做

char arr[3][10];
Run Code Online (Sandbox Code Playgroud)

当我尝试将字符串加载到它时,为什么这样的声明会崩溃。

char * names[3];

for ( int i = 0; i < 3; i++ ) {
    printf("Enter name %d: ", i+1 );
    scanf("%s", names[i]);
}
// print names
printf("\nEntered names are: \n");
for ( int i = 0; i < 3; i++ ) {
    printf("%s\n", names[i] );
}
Run Code Online (Sandbox Code Playgroud)

应该是二维数组吧?因为数组基本上是指针。你能解释一下吗?谢谢。

ana*_*ciu 5

char * names[3];
Run Code Online (Sandbox Code Playgroud)

不是一个二维数组,它是一个包含三个指向 的指针的数组char,如果你想在其中存储char arrays你必须为每个单独的指针分配内存,例如:

for(size_t i = 0; i < 3; i++){
    names[i] = malloc(/*length your array of chars*/);
}
Run Code Online (Sandbox Code Playgroud)

然后你可以char arrays使用你的例子来存储:

for(size_t i = 0; i < 3; i++){
    printf("Enter name %ld: ", i + 1 );
    scanf("%29s", names[i]); //for a malloc size of 30
}
Run Code Online (Sandbox Code Playgroud)

请注意,您必须小心scanf,如果输入的字符串比分配给存储它的内存更长,您将进行堆栈粉碎,即对于names[i]大小为30,您应该使用%29s说明符,而不是%s。尽管这种方法并非没有问题,即stdin缓冲区中可能存在的字符,但它绝对更安全。

或者,您可以为它们分配字符串文字(在这种情况下,最好将数组声明为const,否则如果您尝试编辑一个或多个字符,则会导致段错误):

const char* names[3];

for(size_t i = 0; i < 3; i++){
    names[i] = "My string literal";
}
Run Code Online (Sandbox Code Playgroud)

您还可以让它们指向现有的char arrays

char arr[3][10];
char* names[3];

for(size_t i = 0; i < 3; i++){
    names[i] = arr[i];
}
Run Code Online (Sandbox Code Playgroud)