Присвоение массива char массиву char в C - PullRequest
1 голос
/ 29 февраля 2020

Вы можете помочь мне с этим кодом, я могу скопировать arr в arr2 (из индекса 1 и далее, я не могу до сих пор считать индекс 0), но некоторые другие не могут. Можете ли вы сказать, если что-то здесь не так?

#include <stdio.h>

int main(){
        char arr[] = "char_arr_one";
        char arr2[] = {arr};
        printf("%s\n%s\n", arr, arr2);
        int i;
        for(i=0;i<13;i++){
                printf("%c %c\n", arr[i], arr2[i+1]);
        }
}

это работает на моей системе!

Ответы [ 3 ]

2 голосов
/ 29 февраля 2020

Стандарт C не разрешает присваивать массив другому массиву:

char arr[] = "char_arr_one";
char arr2[] = {arr};        // This does not work.

Почему он работает в конкретной реализации c, как вы сказали, я не знаю, но в целом не должно быть возможности скомпилировать этот код без хотя бы одного предупреждения.

Так, может быть, вы отключили или даже проигнорировали предупреждения?

Здесь есть одна ссылка на этот контекст: Почему я всегда должен включать предупреждения компилятора?

Тем не менее это не даст вам желаемого результата копирования строки "char_arr_one" в arr2.

Если вы хотите сохранить строку, хранящуюся внутри arr, в arr2 вы можете использовать strcpy в заголовке string.h:

char arr[] = "char_arr_one";
char arr2[13];                // You need to provide the amount of elements, at least
                              // as much as are required to store the string inside arr
                              // the null character.
strcpy(arr2,arr);             // Copies the string in arr into arr2.

Обратите внимание, что вам нужно указать элементы arr2, которые должны быть как минимум столько же, сколько требуется для хранения строки "char_arr_one" плюс завершающий нулевой символ \0 при определении arr2. В этом случае arr2 должно иметь как минимум 13 char объектов.

Вы также можете «автоматически» определить размер arr, используя оператор sizeof:

char arr[] = "char_arr_one";
char arr2[sizeof(arr)];       // Automatically detects the size of `arr` and provides
                              // it for specify the required amount of elements for storing 
                              // the string in arr + the null character.

strcpy(arr2,arr);             // Copies the string in arr into arr2.

Кроме того, третий аргумент arr2[i+1] внутри вызова printf приведет вас к неопределенному поведению. На последней итерации будет напечатано что-то, что находится за пределами массива arr2. Поэтому измените это на arr2[i].


Исправленный код должен быть:

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

int main(){
        char arr[] = "char_arr_one";
        char arr2[sizeof(arr)];

        strcpy(arr2,arr);

        printf("%s\n%s\n",arr,arr2);

        for(int i = 0; i < 13; i++){
                printf("%c %c\n", arr[i], arr2[i]);
        }

        return 0;
}

Выход:

char_arr_one
char_arr_one
c c
h h
a a
r r
_ _
a a
r r
r r
_ _
o o
n n
e e
1 голос
/ 01 марта 2020

Я могу скопировать arr в arr2 (из индекса 1 и далее, я не могу до сих пор считать индекс 0), но некоторые другие не могут. .....

На каком основании вы уверены в этом? Я не вижу кода, который копирует arr в arr2 из индекса 1 и далее.

Посмотрите на предупреждение компилятора gcc в операторе, согласно вам, копирование arr в arr2 из индекса 1:

<source>:5:24: warning: initialization of 'char' from 'char *' makes integer from pointer without a cast [-Wint-conversion]

5 |         char arr2[] = {arr};

Значение этого предупреждения -
Имя массива arr затухает до указателя, а указатель преобразуется в целое и присваивается первому элементу arr2 (элемент в 0 th индекс массива arr2).
Обратите внимание, что если char подписано, то результат этого присваивания будет Реализация определена 1) .

При размещении arr и arr2 в стеке на вашем компьютере вы можете получить ожидаемый результат, но на другой платформе / архитектуре вы можете получить другой результат. Обратите внимание, что языковые стандарты C не определяют, как локальные переменные функции должны быть помещены в стек. В стандартах даже нет ни одного упоминания об сегментах памяти (стек, куча и т. Д. 1064 *.). Эти вещи полностью зависят от базовой платформы / архитектуры. Стандарты говорят только о сфере действия и сроке жизни переменных.

Можете ли вы сказать, что здесь что-то не так?

Поскольку вы пропустили измерение arr2, компилятор вычисляет его на основе размера инициализатора. Инициализатор arr2 имеет только элемент 1. Таким образом, размер arr2 будет 1, т.е. arr2 - это массив char только с одним элементом. Здесь вы получаете доступ к arr2 сверх его размера:

    for(i=0;i<13;i++){
            printf("%c %c\n", arr[i], arr2[i+1]);
                                      ^^^^^^^^^

Доступ к массиву сверх его размера неопределенное поведение . Неопределенное поведение включает в себя то, что оно может выполняться некорректно (либо аварийно завершать работу, либо молча генерировать неверные результаты), либо случайно выполнять то, что задумал программист.


1) С C Стандарты # 6.2.5p15

15 The three types char, signed char, and unsigned char are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.45)

1 голос
/ 29 февраля 2020

в C вы не можете присвоить массив массиву.

Вам нужно скопировать его самостоятельно

    char arr[] = "char_arr_one";
    char arr2[sizeof(arr)];

    memcpy(arr2, arr, sizeof(arr);

или

        for(size_t index = 0; index < sizeof(arr); index++)
        {
            arr2[index] = arr[index];
        }

Если я сделаю Ваш пример немного менее тривиален (добавляя другую переменную), результат очевиден. Это не работает.

#include <stdio.h>

int main(){
        char arr[] = "char_arr_one";
        char another[] = "it does not work for sure";
        char arr2[] = {arr};
        printf("%p %p\n", (void *)arr, (void *)arr2);
        printf("%s\n%s\n", arr, arr2);
        int i;
        for(i=0;i<13;i++){
                printf("0x%02hhx - '%c' 0x%02hhx, '%c'\n", arr[i], arr[i],
                  arr2[i], (arr2[i] >= 32 && arr2[i] <= 127) ? arr2[i] : ' ' );
        }
}

https://godbolt.org/z/dvLcqq

И результат:

0x7fff4a68b84f 0x7fff4a68b82f
char_arr_one
Oit does not work for sure
0x63 - 'c' 0x4f, 'O'
0x68 - 'h' 0x69, 'i'
0x61 - 'a' 0x74, 't'
0x72 - 'r' 0x20, ' '
0x5f - '_' 0x64, 'd'
0x61 - 'a' 0x6f, 'o'
0x72 - 'r' 0x65, 'e'
0x72 - 'r' 0x73, 's'
0x5f - '_' 0x20, ' '
0x6f - 'o' 0x6e, 'n'
0x6e - 'n' 0x6f, 'o'
0x65 - 'e' 0x74, 't'
0x20 - '' 0x20, ' '
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...