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

时间:2021-01-23 21:38:09

I am simply trying to print a string of chars using pointers but the output is not correct. Can someone tell me why? The method display_chunks() is meant to print each string in the array except for the first character. But instead seems to print the same line despite the fact that I'm incrementing the pointer variable after printing the last character in a string.

我只是尝试使用指针打印一串字符,但输出不正确。有人可以告诉我为什么吗?方法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");
    }
}

This is my output:

这是我的输出:

i1%fsi%fs%jstwrtzx%
1%fsi%fs%jstwrtzx%
%fsi%fs%jstwrtzx% 1
fsi%fs%jstwrtzx% 1'

EDIT From Craig's answer; I don't seem to understand the difference between a pointer and a double pointer. What I tried earlier was incrementing arr because I assumed it would point to the next array in chuncks. Looks like I was mistaken and it took me a while to figure out.

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

Sorry, new to C : )

对不起,新来的C :)

3 个解决方案

#1


1  

You have two problems.

你有两个问题。

Your for loop for j starts at 1 instead of 0.

你的j循环从1开始而不是0。

And, arr is always chunks[0] instead of chunks[i]

并且,arr总是块[0]而不是块[i]

Here's the corrected code:

这是更正后的代码:

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");
    }
}

UPDATE:

Based on your original code [which did not show the declaration for chunks], the use of arr = chunks[i] was necessary because either of these might have been used:

基于您的原始代码[未显示块的声明],使用arr = chunks [i]是必要的,因为其中任何一个都可能已被使用:

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

Now that the latter is known to be used, a variation on your original code is possible that uses the increment of arr:

既然已知使用后者,则可以使用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");
    }
}

A style cleanup of that could be:

样式清理可能是:

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");
    }
}

#2


1  

To increment arr to point to the next array of characters, it must be the correct type, which is char (*arr)[CHUNK_LENGTH]:

要增加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;
    }
}

#3


0  

Here is a variation of the Craig's answer using %s:

以下是使用%s的Craig答案的变体:

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

And to print starting from the second character:

并从第二个字符开始打印:

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

#1


1  

You have two problems.

你有两个问题。

Your for loop for j starts at 1 instead of 0.

你的j循环从1开始而不是0。

And, arr is always chunks[0] instead of chunks[i]

并且,arr总是块[0]而不是块[i]

Here's the corrected code:

这是更正后的代码:

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");
    }
}

UPDATE:

Based on your original code [which did not show the declaration for chunks], the use of arr = chunks[i] was necessary because either of these might have been used:

基于您的原始代码[未显示块的声明],使用arr = chunks [i]是必要的,因为其中任何一个都可能已被使用:

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

Now that the latter is known to be used, a variation on your original code is possible that uses the increment of arr:

既然已知使用后者,则可以使用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");
    }
}

A style cleanup of that could be:

样式清理可能是:

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");
    }
}

#2


1  

To increment arr to point to the next array of characters, it must be the correct type, which is char (*arr)[CHUNK_LENGTH]:

要增加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;
    }
}

#3


0  

Here is a variation of the Craig's answer using %s:

以下是使用%s的Craig答案的变体:

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

And to print starting from the second character:

并从第二个字符开始打印:

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