为什么在C中打印char类型的2D数组时会得到UB?

时间:2017-07-01 18:01:18

标签: c arrays string multidimensional-array char

我只是尝试使用指针打印一串字符,但输出不正确。有人可以告诉我为什么吗?方法display_chunks()用于打印除第一个字符外的数组中的每个字符串。但是,尽管我在打印字符串中的最后一个字符后递增指针变量,但似乎打印出相同的行。

#include <stdio.h>
#include <string.h>

//macros: constants
#define CHUNK_LENGTH (20+1)  //each chunk has twenty characters, we add 1 so
                           //there is space for the null terminator.
#define NUMBER_OF_CHUNKS 4 //the message is spread across 4 chunks.
void display_chunks();

char chunks[NUMBER_OF_CHUNKS][CHUNK_LENGTH];

int main(){
strcpy(chunks[0], "2i1%fsi%fs%jstwrtzx%");
strcpy(chunks[1], "1'H%nx%vznwp~1%kqf|j");
strcpy(chunks[2], "4R3%Wnyhmnj%%%%%%%%%");
strcpy(chunks[3], "3xzhhjxx3'%2%Ijssnx%");
    display_chunks();
}

void display_chunks() {
    int i, j;
    char *arr = chunks[0];
    for(i = 0; i < NUMBER_OF_CHUNKS; i++){
        for(j = 1; j < CHUNK_LENGTH-1; j++){
            printf("%c", *(arr+j));
        }
        ++arr;
        printf("\n");
    }
}

这是我的输出:

i1%fsi%fs%jstwrtzx%
1%fsi%fs%jstwrtzx%
%fsi%fs%jstwrtzx% 1
fsi%fs%jstwrtzx% 1'
编辑来自克雷格的回答;我似乎并不理解指针和双指针之间的区别。我之前尝试过的是增加arr,因为我认为它会指向chuncks中的下一个数组。看起来我错了,我花了一段时间才弄明白。

对不起,新来的C:)

3 个答案:

答案 0 :(得分:1)

你有两个问题。

j的for循环从1开始,而不是0

并且arr始终是chunks[0]而不是chunks[i]

以下是更正后的代码:

strcpy(chunks[0], "2i1%fsi%fs%jstwrtzx%");
strcpy(chunks[1], "1'H%nx%vznwp~1%kqf|j");
strcpy(chunks[2], "4R3%Wnyhmnj%%%%%%%%%");
strcpy(chunks[3], "3xzhhjxx3'%2%Ijssnx%");

void display_chunks() {
    int i, j;
    for(i = 0; i < NUMBER_OF_CHUNKS; i++){
        char *arr = chunks[i];
        for(j = 0; j < CHUNK_LENGTH-1; j++){
            printf("%c", *(arr+j));
        }
        printf("\n");
    }
}

<强>更新

根据原始代码[显示chunks的声明],使用arr = chunks[i]是必要的,因为 这些可能已被使用:

char *chunks[NUMBER_OF_CHUNKS];
char chunks[NUMBER_OF_CHUNKS][CHUNK_LENGTH];

现在已知使用后者,可以使用arr的增量对原始代码进行修改:

strcpy(chunks[0], "2i1%fsi%fs%jstwrtzx%");
strcpy(chunks[1], "1'H%nx%vznwp~1%kqf|j");
strcpy(chunks[2], "4R3%Wnyhmnj%%%%%%%%%");
strcpy(chunks[3], "3xzhhjxx3'%2%Ijssnx%");

void display_chunks() {
    int i, j;
    char *arr = chunks[0];
    for(i = 0; i < NUMBER_OF_CHUNKS; i++){
        for(j = 0; j < CHUNK_LENGTH-1; j++){
            printf("%c", arr[j]));
        }
        arr += CHUNK_LENGTH;
        printf("\n");
    }
}

样式清理可能是:

strcpy(chunks[0], "2i1%fsi%fs%jstwrtzx%");
strcpy(chunks[1], "1'H%nx%vznwp~1%kqf|j");
strcpy(chunks[2], "4R3%Wnyhmnj%%%%%%%%%");
strcpy(chunks[3], "3xzhhjxx3'%2%Ijssnx%");

void display_chunks() {
    int i, j;
    char *arr = chunks[0];
    for(i = 0; i < NUMBER_OF_CHUNKS; i++, arr += CHUNK_LENGTH){
        for(j = 0; j < CHUNK_LENGTH-1; j++){
            printf("%c", arr[j]));
        }
        printf("\n");
    }
}

答案 1 :(得分:1)

要将arr增加到指向下一个字符数组,它必须是正确的类型,即char (*arr)[CHUNK_LENGTH]

#include <stdio.h>
#include <string.h>

//macros: constants
#define CHUNK_LENGTH (20+1)  //each chunk has twenty characters, we add 1 so
//there is space for the null terminator.
#define NUMBER_OF_CHUNKS 4 //the message is spread across 4 chunks.
void display_chunks();

char chunks[NUMBER_OF_CHUNKS][CHUNK_LENGTH];

int main() {
    strcpy(chunks[0], "2i1%fsi%fs%jstwrtzx%");
    strcpy(chunks[1], "1'H%nx%vznwp~1%kqf|j");
    strcpy(chunks[2], "4R3%Wnyhmnj%%%%%%%%%");
    strcpy(chunks[3], "3xzhhjxx3'%2%Ijssnx%");
    display_chunks();
}

void display_chunks() {
    int i;
    char (*arr)[CHUNK_LENGTH] = chunks;
    for(i = 0; i < NUMBER_OF_CHUNKS; i++)
    {
        printf("%s\n", *arr);
        ++arr;
    }
}

答案 2 :(得分:0)

以下是使用%s

的克雷格答案的变体
void display_chunks() {
    int i;
    for(i = 0; i < NUMBER_OF_CHUNKS; i++){
        char *arr = chunks[i];
        printf("%s\n", arr);
    }
}

从第二个字符开始打印:

void display_chunks() {
    int i;
    for(i = 0; i < NUMBER_OF_CHUNKS; i++){
        char *arr = chunks[i];
        arr++;
        printf("%s\n", arr);
    }
}

https://repl.it/JKHB