Что происходит при использовании «vs» в C?

#c

#c

Вопрос:

Кто-то поднял этот код для меня, что заставило меня задуматься, что там происходит, код выглядит следующим образом из VS 2019:

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

int main()
{
    char y = '5';
    char w = "5";
    printf("size of x %xn",amp;w);
    printf("size of X %Xn", w);
    printf("size of X in number: %d n", w);
    printf("size of Y %dnn", w);

    w = '5';
    printf("size of y %xn", amp;w);
    printf("size of Y %Xn", w);
    printf("size of X in number: %d n", w);
    printf("size of Y %dnn", w);

    return 0;
}
  

Результат выглядит следующим образом:

 size of x 8ff8bb
size of X 30
size of X in number: 48
size of Y 48

size of y 8ff8bb
size of Y 35
size of X in number: 53
size of Y 53
  

Мне интересно, что там происходит на самом деле? кто-то указал, что ‘ — это символ, а » — строка, но если это так, почему здесь можно поместить строку в символ, и почему это результат?

Спасибо за ответы, я понимаю, что это может быть не слишком актуально для использования, но мне интересно, что там происходит, я только недавно вернулся к повторному изучению C

Код скомпилирован и не выдает никаких предупреждений в VS2019

Поиск в Google в основном дает мне результаты о том, как помещать символы в массив и тому подобное, не удалось найти никакой информации об этом поведении

Комментарии:

1. "size of x %xn",amp;w — За исключением того, что он не печатает размер, поскольку amp;w это не размер чего-либо.

2. Это ничего не может вывести, поскольку оно не компилируется .

3. char w = "5"; сгенерирует предупреждение и, скорее всего, не будет делать то, что вы думаете.

4. Выходной текст, похоже, не имеет никакого отношения к выводимым значениям. Например, последние два printf s в каждой группе, очевидно, печатают один и тот же номер, но имеют разный текст.

5. Почему вы сделали свой вывод таким запутанным? Вы печатаете «размер X», чтобы показать значение w . Почему вы делаете это так сложно? Кого вы пытаетесь запутать?

Ответ №1:

Строка — это массив символов, заканчивающийся нулевым символом. Данные здесь:

 "5"
  

Это то же самое, что:

 {'5',''}
  

Когда вы присваиваете значение массива чему-либо в C, вы присваиваете указатель на первый элемент в массиве. Итак, когда вы пишете:

 char w = "5"
  

вы создаете символ и присваиваете его значение ячейке памяти первого элемента в массиве символов, символ недостаточно велик для хранения ячейки памяти.

Выполнение этого:

 printf("size of x %xn",amp;w);
  

Выводится ли местоположение w в памяти

Выполнение этого:

 printf("size of X %Xn", w);
  

выводится значение w, в вашем случае присвоенное адресу массива строк и усеченное, потому что символ char не может соответствовать адресу.

Если вы хотите использовать строку, вы должны сделать это:

 const char * w = "5"
  

Затем вы можете распечатать строку следующим образом:

 printf("string: %srn", w);
  

вы можете распечатать первый символ в массиве одним из следующих способов

 printf("char: %crn", *w);
printf("char: %crn", w[0]);
  

Для второго бита, когда вы назначаете w следующим образом:

 char w = '5';
  

печать amp;w печатает местоположение в памяти.

печать w с %x помощью печатает значение ASCII '5' , равное 0x35

Комментарии:

1. Спасибо за ответ, думаю, тогда он действительно просто усечен

Ответ №2:

Инициализация

 char w = "5";
  

делает две вещи:

  • Определите символьный литерал "5" , который представляет собой некоторую область памяти, содержащую a '5' , за которым следует a NUL ( '' ) .
  • Определите переменную w типа char и инициализируйте ее адресом строкового литерала, то есть адресом памяти, где '5' находится. Преобразуется адрес (указатель), в char который будут потеряны части значения, поскольку char обычно он меньше указателя ( char* ).

С

 printf("size of X %Xn", w);
  

вы печатаете значение char w в шестнадцатеричной форме, которое, вероятно, является младшим значащим байтом адреса строкового литерала.

Вам следует лучше использовать

 printf("size of X %Xn", (unsigned int)w); /* %X = unsigned int */
  

или

 printf("size of X %hhXn", w); /* %hhX = unsigned char or signed char */
  

чтобы формат соответствовал типу аргумента.

Даже если это не изменит результат в вашем случае, это гарантирует, что код printf не обращается к памяти, которая может быть неинициализирована или может содержать несвязанные данные.

Когда я запускал ваш код, в одном случае значение w было 0xA8 напечатано как FFFFFFA8 . В этом случае %hhX будет только печать A8 .

Я не уверен, что именно произойдет, когда вы передадите char значение в функцию printf , в то время как формат указывает функции интерпретировать данные как unsigned int . Это может зависеть от соглашений о вызовах вашей платформы и реализации компилятора. Возможно, на вашей платформе все аргументы более коротких типов данных преобразуются в int или unsigned int .

Комментарии:

1. Выполняем printf("size of X %hhXn", w); и printf("size of X %Xn", (unsigned int)w); даем тот же результат, что и раньше Спасибо за ответ