2017-02-02 4 views
2

Спасибо за ответы, все были полезны, помогая мне понять, как это работает.Друг прислал мне фрагмент, который я не понимаю. Как это работает?

Друг прислал мне этот кусок кода С, спрашивающий, как он работает (он тоже не знает). Обычно я не работаю с C, но это вызвало мой интерес. Я потратил некоторое время, пытаясь понять, что происходит, но в конце концов я не мог полностью понять это. Вот код:

void knock_knock(char *s){ 
while (*s++ != '\0') 
    printf("Bazinga\n"); 
} 

int main() { 
int data[5] = { -1, -3, 256, -4, 0 }; 
knock_knock((char *) data); 
return 0; 
} 

Первоначально я думал, что это просто фантазия способ печати данных в массиве (да, я знаю: \), но тогда я был удивлен, когда я увидел, что это не напечатайте «Bazinga» 5 раз, но 8. Я искал материал и выяснял, что он работает с указателями (общий любитель, когда дело доходит до c), но я все еще не мог понять, почему 8. Я искал немного больше и нашел что обычно указатели имеют 8 байтов длины в C, и я подтвердил, что, печатая sizeof (s) перед циклом, и, конечно же, это было 8. Я думал, что это все, это просто повторяется по длине указателя, поэтому было бы разумно, что он напечатал Bazinga 8 раз. Мне также стало ясно, почему они используют Bazinga в качестве строки для печати - данные в массиве должны были быть просто отвлечением. Поэтому я попытался добавить больше данных в массив, и, конечно же, он продолжал печатать 8 раз. Затем я изменил первый номер массива, -1, чтобы проверить, действительно ли данные были бессмысленными или нет, и именно здесь я был в замешательстве. Он больше не печатался 8 раз, а только один раз. Разумеется, данные в массиве были не просто приманкой, но и для жизни я не мог понять, что происходит.

+1

Функция указывает значения int (4 байта) с указателем char, которые указывают символы (1 байт) ..... – LPs

+1

Добавить 'printf ("% 08X -% 08X -% 08X \ n ", data [0 ], данные [1], данные [2]); 'перед вызовом функции и увидеть результат ... – LPs

+1

Не вызывает ли это неопределенное поведение? – George

ответ

6

Используя следующий код

#include<stdio.h> 

void knock_knock(char *s) 
{ 
    while (*s++ != '\0') 
     printf("Bazinga\n"); 
} 

int main() 
{ 
    int data[5] = { -1, -3, 256, -4, 0 }; 
    printf("%08X - %08X - %08X\n", data[0], data[1], data[2]); 
    knock_knock((char *) data); 
    return 0; 
} 

Вы можете видеть, что HEX значение data массива

FFFFFFFF - FFFFFFFD - 00000100 

Функция knock_knock печати Bazinga до заостренного значения 0x00 благодаря

while (*s++ != '\0') 

B ut указатель здесь указывает на символы, поэтому указывается один байт каждого цикла, и поэтому первый 0x00 достигнут доступа к «первому» байту третьего значения массива.

1

Легко понять, что здесь происходит, если вывести массив в шестнадцатеричном виде в виде массива символов. Здесь показано, как это сделать

#include <stdio.h> 

int main(void) 
{ 
    int data[] = { -1, -3, 256, -4, 0 }; 
    const size_t N = sizeof(data)/sizeof(*data); 

    char *p = (char *)data; 

    for (size_t i = 0; i < N * sizeof(int); i++) 
    { 
     printf("%0X ", p[i]); 
     if ((i + 1) % sizeof(int) == 0) printf("\n"); 
    } 

    return 0; 
} 

Выход программы

FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 
FFFFFFFD FFFFFFFF FFFFFFFF FFFFFFFF 
0 1 0 0 
FFFFFFFC FFFFFFFF FFFFFFFF FFFFFFFF 
0 0 0 0 

Так строка "Bazinga" будет выводиться столько раз, сколько есть ненулевые байты в представлениях целых чисел в массив. Как видно, первые два отрицательных числа не имеют нулевых байтов в своих представлениях.

Однако номер 256 в любом случае имеет такой байт в самом начале его внутреннего представления. Таким образом, строка будет выводиться ровно восемь раз при условии, что sizeof(int) равно 4.

4

Вам нужно посмотреть на представление данных в целочисленном массиве data.Предполагая, что целое число 4 байта, Представление ниже, дает число в шестнадцатеричной

-1 --> FF FF FF FF 
-3 --> FF FF FF FD 
256 --> 00 00 01 00 
-4 --> FF FF FF FC 
0 --> 00 00 00 00 

Массив data эти номера, сохраненные в формате little- Endian. То есть LSbyte на первом месте. Так,

data ={FF FF FF FF FD FF FF FF 00 01 00 00 FC FF FF FF 00 00 00 00}; 

Функция knock_knock проходит через этот побайтно данных и печатает Bazinga для каждого ненулевого. Он останавливается при первом найденном нуле, который будет после 8 байтов.

(Примечание: размер целого может быть 2 или 8 байтов, но при условии, что размер вашего указателя составляет 8 байтов, я предполагаю, что размер целых чисел равен 4 байтам).

Смежные вопросы