2015-09-12 4 views
3

Я смущен тем, как работает это кастинг, как показывают мои коды ниже, массив из 1 2 3 4 5 будет преобразован в массив символов 1 '\ 0 ». Как это работает?Что происходит, когда вы вводите целочисленный массив в массив символов

#include<stdio.h> 
#include<string.h> 
#define SIZE 5 

int main(){ 
    int array1[SIZE] = { 1, 2, 3, 4, 5 }; 
    int array2[SIZE]; 
    char* array = (char*)array1; 
    int i = 0; 
    while(array[i] != '\0'){ 
    printf("%d ", array[i]); 
    i++; 
    } 
} 
+3

Вы не бросаете массив, а указатель на массив. – Olaf

ответ

3

Что вы делаете здесь, называется типа каламбурная и нахмурился-на. [Редактировать:, добавив комментарий Олафа здесь: Это потому, что литье в вашем коде происходит на указателе, а не на данных, на которые оно указывает.] Из того, что вы описываете, вы находитесь на малоэтажной архитектуре - при условии, что это 32-битный, int из 1 будет принимать 4 байта (32 бита) и представлены следующим образом:

{ 1, 0, 0, 0 } 

так весь ваш массив, интерпретируется как последовательность байтов, выглядит как

{ 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, ... } 

Обратите внимание, что это действительно зависит от вашей реализации и архитектуры. o как раз не делаем type punning. Вот почему стандарт объявляет доступ к сохраненному значению с помощью указателя другого типа, кроме объявленного неопределенного поведения. (Или, в данном случае, как тип-каламбуры к char * является исключением для предоставления некоторых необходимых случаев использования, от реализации поведения - вы все равно получите разные результаты на разных средах)

+2

Я не думаю, что ваш метод представления байтов в int является точным или информативным. Что означает {1, 0, 0, 0}? Просто напишите шестнадцатеричное значение ... – DIMMSum

+0

Я говорю о байтах, так что это довольно ясно. hex - это еще один способ написать контент, а не десятичный. Если вы действительно хотите перейти на уровень машины, попробуйте выполнить двоичный код и посмотрите, насколько это возможно. –

+2

Нет никакого неопределенного поведения с типом пиннинга здесь. Совершенно законно обращаться к любому объекту с помощью указателя на символ. –

1

Результатом является реализации-. Это зависит от endianess на вашей машине; в случае x86 это малоконкурентность.

array является указателем на array1. Как ваша машина, по-видимому, мало-младшему (я думаю, x86), array1 внутри выглядит следующим образом, предполагая, что sizeof(int) равна 4:

0x01 | 0x00 | 0x00 | 0x00 | 0x02 | 0x00 | 0x00 | 0x00 | 0x03 | ... 

Итак, как вы видите, первое значение char «s является 0x01, 0x00 следует. Поэтому результат.

+1

Нет, это * little endian * - и использование * побитового или * оператора на самом деле не прибивает его. –

+0

@FelixPalmen Конечно, ваше право об энсианстве, но интерпретация вертикальных линий как операторов 'or' немного надуманна, IMO. – Downvoter

+0

@cad, так как это о C, я бы просто избегал такой путаницы ... с поразрядным или с некоторыми значениями, записанными в шестнадцатеричном виде, это то, что вы могли видеть довольно часто, например. системный или встроенный C-код, поэтому я прокомментировал это;) –

0

Это из-за размера int 4 байта, но размер символа составляет 1 байт. В этом случае, когда вы передаете вам char в int (от 1 байт до 4), вы получите 4 символа из 1 int. Давайте попробуем

#include<stdio.h> 
#include<string.h> 
#define SIZE 5 

int main(){ 
int array1[SIZE] = { 1, 2, 3, 4, 5 }; 
int array2[SIZE]; 
char* array = (char*)array1; 
int i = 0; 
while(array[i] != '\0'){ 
    printf("%d ", array[i]); 
    i=i+4; 
} 
} 
+0

Обратите внимание, что код OPs будет показывать тот же результат на 64-битной основе. 32bit был всего лишь предположением в моем ответе, чтобы объяснить, что происходит. –

+1

Разве это не UB, когда 'sizeof (int)' равно 4? Я имею в виду, что цикл будет обращаться к недопустимым ячейкам памяти за массивом, не так ли? –

+0

@CoolGuy, да, должен быть добавлен перерыв, вы правы – Dmitry